synchronized初学
基础总结(what)
接触java开发已经将近一年,一直以来只是单纯的运用公司提供的框架,按照固定的模式去实现业务功能。如今回想,想要在java开发上更进一步,于是首先想理解掌握java并发编程
想学习并发编程,就算我什么都不了解也是知道synchronized关键字的,其作用是为了控制多个线程访问共享资源时的并发安全问题,通过资料收集了解到:
1. 当两个及以上的线程访问同一个对象的同一个synchronized同步代码块时,仅能有一个线程能竞争到改资源得到执行,另外一个线程必须等到当前执行线程完成之后,继续竞争改同步代码块的执行权;
2. 当有一个线程正在访问一个object对象的一个synchronized同步代码块时,其他线程对该object对象的所有其他synchronized代码块访问将会被阻塞;
3. 一个线程任务在执行时可以多次获取同一个对象锁,如:一个线程方法在一个对象上调用了一个同步方法,而该同步方法又调用了该对象本身的另外的同步对象方法。此时,jvm会跟踪对象被加锁的次数,一个对象被解锁一次,对象锁的数量-1,每当任务中给每次在对象上获得锁的时候,锁的数量就+1;(可以知道只有在开始竞争到锁成功的线程任务才能多次获得锁),因为每当任务离开一次synchronized方法时,锁的数量就减去1,逐次递减,直到锁的数量变为0,该资源被完全释放,其他任务可以开始竞争使用此资源;
何时使用(when)
Brian同步规则:如果你正在"写"一个变量,它可能接下来将被另一个线程"读"取,或者正在"读"取一个上一次已经被另一个线程"写"过的变量,那么你必须使用同步,并且,"读"/"写"线程都必须用相同的监视器锁同步。
如何使用(how)
- synchronized 方法:
public synchronized void operateName(int n){}
特定对象所有synchronized方法共享同一个锁,这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
不光如此,静态方法也可以声明为 synchronized ,以控制其对类的静态成员变量的访问。
public static synchronized void operateName(int n){}
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率。
典型地,若将线程类的方法 run() 声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
- synchronized 块:
synchronized(SyncObject.Class) { //允许访问控制的代码 }
亦可写成如下格式,this--指的就是当前这个类
synchronized(this) { //允许访问控制的代码 }
synchronized 块中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
在使用synchronized 块的时候,一定要遵循Brian同步规则,并对每个访问临界共享资源的方法都进行同步。
参考:
https://blog.csdn.net/yuan1013922969/article/details/54971632