Java 使用synchronized达到多线程同步

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41723615/article/details/88685232
A线程先持有object对象的Lock锁,B线程可以以异步的方式调用object对象中的非synchronized类型的方法。

A线程先持有object对象的Lock锁,B线程如果在这时调用object对象中的synchronized类型 的方法则需等待,也就是同步。

脏读:在读取实例变量时,此值已经被其他线程更改过了。不同线程争抢实例变量的结果。

为了避免数据出现交叉的情况,使用synchronized关键字来进行同步。
当A线程调用anyObject对象加入synchronized关键字的X方法时,A线程就获得了X方法锁,就是获得了对象的锁,所以其他线程必须等A线程执行完毕才可以调用X方法,但B线程可以随意调用其他的非synchronized同步的方法。

如果B线程声明了synchronized关键字的非X方法时,必须等待A线程将X方法执行完,也就是释放对象锁后才可以调用。此时A线程执行了一个完整的任务,这时就不存在脏读的情况。

synchronized锁重入:当一个线程得到一个对象锁后,再次请求得到此对象锁。
在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的。

可重入锁的概念是:自己可以再次获取自己的内部锁。比如有一条线程获得了某个对象的锁,此时这个对象锁还没有释放,当 其再想要获取这个对象的锁的时候还是可以获取的,
如果不可锁重入的话,就会造成死锁。
可重入锁也支持父子继承的环境中。

当一个线程执行的代码出现异常时,其所持有的锁会自动释放。
同步不具有继承性。

synchronized同步语句块:
synchronized声明方法的弊端:比如A线程调用同步方法执行了一个长时间的任务,那么B线程则必须等待比较长时间,
在这样的情况下可以使用synchronized同步语句块来解决。

synchronized同步代码块的使用:
当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行,
另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

如何用synchronized同步代码块解决程序执行效率低的问题呢?
当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。

synchronized代码块间的同步性:
当一个线程访问object的一个synchronized()同步代码块时,其他线程对同一个object中的所有其他synchronized(this)同步代码块的访问将被阻塞。
同步synchronized(this)代码块是锁定当前对象的。

将任意对象作为对象监视器:
多个线程调用同一个对象中的不同名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的。

synchronized同步方法、synchronized(this)同步代码块:
1.对其他synchronized同步方法、synchronized(this)同步代码块调用出现阻塞状态。
2.同一时间只有一个线程可以执行synchronized同步方法或synchronized(this)同步代码块的代码。
锁非this对象具有一定的优点:如果在一个类中有很多个synchronized方法,这时虽然能实现同步,但会受到阻塞,所以影响效率;
但是如果使用同步代码块锁非this对象,则synchronized(非this)代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁,则可以大大提高运行效率。
使用synchronized(非this对象X)同步代码块格式进行同步操作时,对象监听器必须是同一个对象。如果不是同一个对象监视器,运行的结果就是异步调用了,就会交叉运行。
同步代码块放在非同步synchronized方法中进行声明,并不能保证调用方法的线程执行同步/顺序性,也就是线程调用方法的顺序是无序的,虽然在同步块中执行的顺序是同步的,这样极易出现脏读的情况。

synchronized(非this对象x)格式的写法是将x对象本省作为对象监听器:
1.当多个线程同时执行synchronized(x){}同步代码时呈同步效果。
2.当其他线程执行x对象中synchronized同步方法时呈同步效果。
3.当其他线程执行x对象方法里面的synchronized(this)代码块时也是呈现同步效果。
静态同步synchronized方法与synchronized(class)代码块。
关键字synchronized还可以应用在static静态方法上,对当前的*.java文件对应的Class类进行持锁。
Class锁可以对类的所有对象实例起作用。
数据类型String的常量池特性:
在JVM中具有String常量池缓存的功能。
同步synchronized代码块都不使用String作为锁对象,而改用其他,例如 new Object()实例化一个Object对象,但它并不放入缓存中。
同步synchronized方法无限等待与解决:
同步方法容易造成死循环,使用同步块可以解决此问题。
多线程给的死锁:只要互相等待对方释放锁就有可能出现死锁。
内置类与静态内置类:
在内置类中有两个同步方法,但使用的却是不同的锁,打印的结果也是异步的。
同步代码块synchronized(class)对class上锁后,其他线程只能以同步的方法调用class中的静态同步方法。
锁对象的改变:
在任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,
如果同时持有相同的锁对象,则这些线程之间就是同步的;
如果分别获取锁对象,这些线程之间就是异步的。
只要对象不变,即使对象的属性被改变,运行的结果还是同步的。

猜你喜欢

转载自blog.csdn.net/qq_41723615/article/details/88685232