Talk about the synchronized keyword

  I think this is a very crucial keyword keyword. But the beginning of the study and did not frequently used. why? Business scene constraints, stand-alone single-threaded really rarely used. So what use is it?

  Because it is multi-threaded solve a critical member of synchronization.

  Most of the content comes from inside: Author: SnailClimb

 Let me talk about the understanding of synchronized

   synchronized keyword solution is to access resources between multiple threads synchronization , synchronized keyword can be guaranteed by its modified method or block of code at any time, only one thread of execution.

  Lock in a thread is to ensure safe and effective solutions.

  Further, in the Java earlier versions, the synchronized belongs heavyweight lock , inefficient, since the monitor lock (monitor) is dependent on the underlying operating system to achieve Mutex Lock, Java threads are mapped to the operating system's native threads Up. To wake up a thread or suspend, the operating system needs to help complete, the need to convert from user mode to kernel mode when switching between threads operating system implementation, the transition between a state requires a relatively long time, time cost relatively high, which is why early synchronized low efficiency reasons. Fortunately, after Java 6 Java JVM-level official from the larger synchronized optimization, so now synchronized lock efficiency is optimized quite well. JDK1.6 lock achieved it introduced a number of optimization, such as spin lock spin lock adaptability, to eliminate the lock, the lock roughening biased locking, lightweight and other techniques to reduce lock overhead lock operations.

  Summary: We want to understand this key, it is necessary to use, but also use less. I think there is a computer conservation issues, security, and speed is equivalent to fish and can not have both. Want to ensure the safety of access, it must sacrifice performance speed.

synchronized keyword main used in three ways

 Examples of modified method , the current applied to the lock object instance, before entering the synchronization code to obtain the current lock object instance

 Modification of static methods , the role of the current class object locking, before entering the lock synchronization code to obtain the current class object. That is to lock the current class, will apply to all object instances of the class, because static members do not belong to any instance of an object, the class members (static indicates that this is a static resource class, no matter how many new objects, only a, so all objects of that class have added lock). So if a thread A non-static synchronized method calls an instance of an object, and the thread B needs to call this static synchronized method belongs to the class of the object instance, is allowed, mutual exclusion will not happen, because access static synchronized method lock is occupied the current class locks, access to non-static synchronized method lock is occupied by the current instance of the object lock.


  Modifying the code block , designated lock object, to lock a given object, before entering the synchronization code library to obtain a given lock of the object. A method as synchronized and synchronized (the this) is a locking block of the current object. static synchronized keyword added and synchronized static methods (class) is the code block is locked to the class Class. Here mention about: synchronized keyword is added to the static method is non-static object instance to lock. Another thing to note is: try not to use synchronized (String a) because the JVM, the string constant pool has a buffer function!

 Talk about the underlying principles of the synchronized keyword

synchronized keyword underlying principle belong JVM level.
① synchronized case statements sync blocks

public class SynchronizedDemo {
public void method() {
synchronized (this) {
System.out.println("synchronized 代码块");
}
}
}


See SynchronizedDemo JDK classes by carrying javap related command byte code information: first switch to the corresponding directory, being executed the javac
SynchronizedDemo.java command .class files to generate compiled and then executed -C -s -v -l javap
SynchronizedDemo .class.

From the above we can see:
implement synchronized sync block of statements using the monitorenter and monitorexit instructions , wherein monitorenter instruction start position of the synchronization code points to blocks, monitorexit instruction indicating the end position of the synchronization code block. When performing monitorenter instruction thread tries to acquire a lock that is eligible monitor (monitor object exists in the subject header of each Java object, synchronized lock is acquired in this way locks, it is why any object in Java can be used as a lock reason) the holder of the right. when the counter is 0 can succeed, will acquire the lock counter is set to 1 plus 1. After performing the appropriate monitorexit instruction, the lock counter is set to 0, indicating that the lock is released. If the lock fails to obtain the object that the current thread will block until another thread lock is released.

Case ② synchronized modification of the method

public class SynchronizedDemo2 {
public synchronized void method() {
System.out.println("synchronized 方法");
}
}

  synchronized modification of the method does not monitorenter instructions and monitorexit command, made on behalf of the really ACC_SYNCHRONIZED identifier, which indicates that the method is a synchronous method, JVM through the ACC_SYNCHRONIZED access flag to identify if a method is declared as synchronization method to perform corresponding synchronous call. 

After the bottom of the synchronized keyword JDK1.6 talk about what had been done to optimize

  JDK1.6 对锁的实现引入了大量的优化,如偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销。
  锁主要存在四种状态,依次是:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,他们会随着竞争的激烈而逐渐升级。注意锁可以升级不可降级,这种策略是为了提高获得锁和释放锁的效率。

锁的在单例模式中的使用

双重校验锁实现对象单例(线程安全)

public class Singleton {
  private volatile static Singleton uniqueInstance;
  private Singleton() {
 }
  public static Singleton getUniqueInstance() {
   //先判断对象是否已经实例过,没有实例化过才进入加锁代码
      if (uniqueInstance == null) {
      //类对象加锁
      synchronized (Singleton.class) {
        if (uniqueInstance == null) {
          uniqueInstance = new Singleton();
       }
     }
   }
    return uniqueInstance;
 }
}

另外,需要注意 uniqueInstance 采用 volatile 关键字修饰也是很有必要。
 uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:
  1. 为 uniqueInstance 分配内存空间
  2. 初始化 uniqueInstance
  3. 将 uniqueInstance 指向分配的内存地址
  但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出先问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。
使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。

synchronized的兄弟姐妹

https://blog.csdn.net/star1210644725/article/details/92982257

 

Guess you like

Origin blog.csdn.net/star1210644725/article/details/93219414