所有的代码在单线程时,都不会出问题。
多线程就有可能出现问题,多个线程访问同一个资源,会导致资源发生问题。
我们期望在某些代码统一执行,不被其他线程打断。
所有对象都有1把锁,每个锁都有各自的计数器
1、在代码块声明同步 指定对象
2、非静态方法上声明同步 this
3、静态方法上声明同步 当前类.class
一、线程同步概念
线程同步是指在访问共享资源时多个线程相互间的协调和控制。
样例1:
样例2:偶数生成器
二、实现线程同步
1、Synchronized使用方式:
同步代码块:锁对象可以自己指定,任何类型都可以充当锁对象,多个线程对代码块中的代码要想达到互
斥执行的效果,那么多个线程需要共享相同的锁对象,选取依据就是只要满足共享性,当下的环境有有什
么对象就用什么对象
当代码块包含了整个方法的内容,就可以把synchronized写在方法上
同步非静态方法:锁对象就是this
同步静态方法:锁对象为当前类.class
2、Synchronized工作机制
只有一个线程持有锁对象的监视器的时候,该线程才能执行同步代码块中的代码, 同步代码块执行完之
后,会释放锁对象的监视器,同样一个锁对象的监视器同一时刻,只能被1个线程拥有,锁对象监视器会
有一个计数器(count),当一个线程执行同步代码块的时候,会对计数器,进行判断,如果是默认
值,就进入同步代码块,并对计数器进行自加,执行完毕之后,计数器进行自减,如果计数器不是默认
值,那么表示锁对象的监视器被另外一个线程正在持有,就无法进入
3、释放锁对象监视器
一个线程能进入同步代码块,必须持有锁对象的监视器,此时,其他线程不能同时持有锁对象的监视
器,必须等待目前持有锁对象监视器的线程释放锁对象的监视器。如何释放:
同步代码块执行结束
wait(必须使用在同步代码块中)
三、线程协作:
等待唤醒机制,实现线程间的通信和协作,必须建立在互斥的基础上
wait:交出锁对象的监视器,释放cpu的使用权,锁对象.wait(),wait结束之后,线程回到就绪状态
notify:唤醒等待当前锁对象监视器的线程之一,锁对象.notify();
notifyAll: 唤醒等待当前锁对象监视器的所有线程,锁对象.notifyAll();
样例1:
样例2:
样例3:
生产者消费者模式
单生产者单消费者
多生产者多消费者模式
四、线程同步的应用:
懒汉式单例模式线程不安全
双重锁机制
五、死锁
多个线程在竞争资源的时候出现了互相等待的情况
sleep 和 wait的区别
sleep是Thread类中的静态方法,wait是Object类中非静态方法方法
sleep方法不是必须在同步代码中调用,wait必须在同步代码中调用
Sleep方法直接通过Thread类名调用,wait需要通过同步代码中的锁对象调用
Sleep不会交出锁对象的监视器,wait会交出锁对象的监视器