线程同步
一、为什么要线程同步?
当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题。 比如一些读写操作。
二、名词解释:
同步:协同步调,按预定的先后次序进行运行,协同、协助、互相配合的意思。如:你说完,我再说。而线程同步呢,就是线程排队执行,避免同时对共享资源进行操作。
异步:异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。
三、场景:
多线程并发时,多个线程同时请求同一个资源,会导致此资源的数据混乱,A线程修改B线程的处理的数据,而B线程又修改A线程处理的数理。这是由于全局资源造成的,为了解决此问题,优先考虑使用局部变量,或者使用同步方法、同步代码块、等线程的同步机制。
同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求不到,怎么办,A线程只能等待下去
异步:A线程要请求某个资使用同步对象源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程仍然请求的到,A线程无需等待
四、同步机制的具体实现:
1、synchronized 同步方法,
2、synchronized 同步块,
3、synchronized 同步对象 (其实就是将对象的当前实例作为同步锁,而static synchronized控制类的所有实例的访问)
4、使用 volatile 关键词修饰的变量
5、使用ReentrantLock 主动加锁和释放锁
注:synchronized关键字可以修饰方法,也可以修饰代码块,但不能修饰构造器,属性等。synchronized关键字是不能继承的,继承时子类的覆盖方法必须显示定义成synchronized。
五:注意点
实现同步机制注意以下几点:
1、线程同步是非常耗费资源的一种操作。我们要尽量控制线程同步的代码段范围。同步的代码段范围越小越好。(同步锁竞争)
2,不要对线程安全类的所有方法都进行同步,只对那些会改变共享资源方法的进行同步。
3,安全性高,性能低,在多线程用。性能高,安全性低,在单线程用。
4、如果可变类有两种运行环境,单线程环境和多线程环境则应该为该可变类提供两种版本:在单线程中环境中,使用线程不安全版本以保证性能,在多线程中使用线程安全版本保证安全。
5、多个线程访问共享资源的代码有可能是同一份代码,但如果访问同一份共享资源的是不同的代码段,应该加上同一个同步锁;如果加的是不同的同步锁,那么根本就起不到同步的作用,没有任何意义。也就是说 同步锁本身也一定是多个线程之间的共享对象。
6、如果一个同步代码块和非同步代码块同时操作共享资源,仍然会造成对共享资源的竞争。
六:其他
ThreadLocal与同步机制
ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题,前者采用以"空间换时间"的方法,后者采用以"时间换空间"的方式
线程状态图
多个线程有同一个同步代码块时,需要在就绪队列等待执行。执行完成,释放锁,让下一个线程获取,执行。