美文网首页
线程的同步与死锁

线程的同步与死锁

作者: 曾梦想仗剑天涯 | 来源:发表于2020-12-01 15:51 被阅读0次
  • 在多线程处理之中可以利用Runnable描述多个线程操作的资源,而Thread类描述每一个线程对象,于是当多个线程访问统一资源的时候如果处理不当就会产生数据的错误操作;

同步问题的引出

  • 下面编写一个卖票程序,将创建若干个线程对象实现买票的处理操作;
//
package com.company;
class MyThread implements Runnable {
    private int ticket = 10;
    @Override
    public void run() {
        while (true) {
            if (this.ticket > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出去一张票,当前还剩" + this.ticket--);
            } else {
                System.out.println("******* 票卖完了 *******");
                break;
            }
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        MyThread mt = new MyThread();
        Thread threadA = new Thread(mt, "票贩子A");
        Thread threadB = new Thread(mt, "票贩子B");
        Thread threadC = new Thread(mt, "票贩子C");
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
  • 此时的程序将创建三个线程对象,并且这三个线程对象将进行10张票的出售,此时的程序在进行买票处理的时候并没有任何的问题(假象),下面模拟一下卖票中的延迟操作:
if (this.ticket > 0) {
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
         e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + "卖出去一张票,当前还剩" + this.ticket--);
} else {
    System.out.println("******* 票卖完了 *******");
    break;
}
  • 追加了延迟问题就暴露出来了,但是这个问题是一直都在的;
此图来源于李兴华老师

线程同步处理

  • 经过分析之后已经可以确认同步问题所产生的主要原因,那么就需要进行同步问题的解决,但是解决同步问题的关键是锁,指的是当某一个线程执行操作的时候,其他线程外面等待;
此图来源于李兴华老师
  • 如果要想在程序之中实现这把锁的功能,可以使用synchronized关键字来实现,利用此关键字可以定义同步方法或同步代码块,在同步代码块的操作里面的代码只允许一个线程执行:
    synchronized(同步对象) {
    同步代码操作;
    }
  • 一般进行同步对象处理的时候可以采用当前对象this进行同步;
//利用同步代码块解决数据同步访问问题
synchronized (this) {
    if (this.ticket > 0) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "卖出去一张票,当前还剩" + this.ticket--);
    } else {
        System.out.println("******* 票卖完了 *******");
        break;
    }
}
  • 加入同步处理之后,程序的整体性能下降了,同步实际上会造成性能的降低;
//利用同步方法解决:只需要在方法定义上使用synchronized关键字即可
package com.company;
class MyThread implements Runnable {
    private int ticket = 10;
    public synchronized boolean sale() {
        if (this.ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "卖出去一张票,当前还剩" + this.ticket--);
            return true;
        } else {
            System.out.println("******* 票卖完了 *******");
            return false;
        }
    }
    @Override
    public void run() {
        while (this.sale()) {
            ;
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        MyThread mt = new MyThread();
        Thread threadA = new Thread(mt, "票贩子A");
        Thread threadB = new Thread(mt, "票贩子B");
        Thread threadC = new Thread(mt, "票贩子C");
        threadA.start();
        threadB.start();
        threadC.start();
    }
}

线程的死锁

  • 死锁是在进行多线程同步的处理之中有可能产生的一种问题,所谓的死锁指的是若干个线程彼此等待的状态;
//死锁的展示
package com.company;
public class DeadLock implements Runnable {
    private LockA a = new LockA();
    private LockB b = new LockB();
    @Override
    public void run() {
        a.say(b);
    }
    public DeadLock() {
        new Thread(this).start();
        b.say(a);
    }
    public static void main(String[] args) {
        new DeadLock();
    }
}
class LockA {
    public synchronized void say(LockB b) {
        System.out.println("线程A说:线程B你让我先运行");
        b.get();
    }
    public synchronized void get() {
        System.out.println("线程B说了让我先运行");
    }
}
class LockB {
    public synchronized void say(LockA a) {
        System.out.println("线程B说:线程A你让我先运行");
        a.get();
    }
    public synchronized void get() {
        System.out.println("线程A说了让我先运行");
    }
}
  • 死锁造成的主要原因是因为彼此都在互相等待,等待对方先让出资源,死锁实际上是开发中出现的不确定的状态;
  • 若干个线程访问同一资源时一定要进行同步处理,而过多的同步会造成死锁;

相关文章

  • 并发 :线程间同步、锁、可重入锁及互斥锁

    线程间同步 线程间同步涉及线程互斥锁; 锁(Lock)容易导致死锁,可重入锁(RLock)则不会导致死锁,但每次 ...

  • 线程的同步与死锁

      在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,当然多个...

  • 线程的同步与死锁

    在多线程处理之中可以利用Runnable描述多个线程操作的资源,而Thread类描述每一个线程对象,于是当多个线程...

  • GCD分析(中)

    同步函数死锁 死锁现象 主线程因为同步函数的原因等着先执⾏任务 主队列等着主线程的任务执⾏完毕再执⾏⾃⼰的任务 主...

  • Java 并发编程——同步与死锁

    1. 同步与死锁 1.1 同步 说到线程,同步是一个不得不说的话题,为什么呢?因为多个线程访问同一资源时,如果不进...

  • Synchronized关键字详解2(对非object持锁)

    4.死锁:同步方法容易造成死锁。Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待根本不可能被释放的锁...

  • 04.关于线程你必须知道的8个问题(下)

    大家好,我是王有志。 今天我们来学习线程中最后4个问题: 线程的同步与互斥 线程的本质与调度 死锁的产生与解决 多...

  • 关于主线程执行同步任务造成死锁的思考

    经典问题重现 bug 粘贴主线程+同步造成死锁 要想明白,为什么造成死锁,首先要搞懂主线程是干嘛的 主线程程序运行...

  • iOS 多线程面试题(死锁)

    死锁 死锁就是队列引起的循环等待 1、一个比较常见的死锁例子:主队列同步 在主线程中运用主队列同步,也就是把任务放...

  • 多线程之GCD

    GCD术语 串行和并行 同步和异步 关键段 竞争条件 死锁 线程安全 线程上下文切换 平行与并发 平行:多个线程可...

网友评论

      本文标题:线程的同步与死锁

      本文链接:https://www.haomeiwen.com/subject/cquswktx.html