1, Foreword
Have you ever thought about whether the + + operation in Java is thread safe? That is, in the case of multithreading, if multiple threads execute the + + operation together, will the result be what we expect? You can write a demo to verify it.
public static int count = 0; public static void main(String[] args) { for (int j = 0; j < 10000; j++) { new Thread(new Runnable() { @Override public void run() { add(); } }).start(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); } public static void add(){ count++; } Copy code
The final execution result is shown in the figure below:
Obviously, the + + operation in Java is not thread safe. This involves how to ensure thread safety when operating the same variable or method in a multithreaded environment.
2, Synchronized
What is Synchronized?
The Synchronized keyword is to set a lock with a specific object. When multiple threads access concurrently, only one thread is allowed to obtain the lock and execute the code. After the code is executed, release the lock and continue to compete with other threads.
Use of Synchronized
We can slightly modify the above demo to make + + operation thread safe.
public static int count = 0; public static void main(String[] args) { for (int j = 0; j < 10000; j++) { new Thread(new Runnable() { @Override public void run() { add(); } }).start(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); } public synchronized static void add(){ count++; } Copy code
Just make a small change, that is, add the synchronized keyword to the add() method. Take a look at the execution results:
The result of multiple executions is 10000, which is in line with our expectations. The add() method has also become a thread safe method.
Usage scenarios for Synchronized
Synchronized has three different usage scenarios, which also correspond to different lock objects.
1.Synchronized code block
Modify the add() method of the demo above
public static void add(){ Object o = new Object(); //Lock object synchronized (o){ count++; } } Copy code
Define an Object object as a lock Object, and only one thread will obtain the lock Object and execute + + operations. Other threads need to wait for the lock Object to be released, scramble for the lock Object, and those who obtain the lock Object can continue to execute + +.
2.Synchronized method
public synchronized void add(){ ... ... } Copy code
What is the lock object in the add() method? Obviously, it is the current object of this. The thread obtains the current object.
3.Synchronized static method
public synchronized static void add(){ count++; } Copy code
The last one is the add() method in the demo. At this time, the lock object is the bytecode object of the current class. Because it is a static method and the static method belongs to this class, the lock object is the bytecode object of the current class.
summary
Synchronized Using in a code block, the lock object can be any object. Synchronized In the method used, the lock object is the current object this. Synchronized Used in static methods, the lock object is the bytecode object of the current class. Copy code
3, Common uses of Synchronized classes
Vector is thread safe, ArrayList and LinkedList are thread unsafe, Properties are thread safe, HashSet and TreeSet are thread safe, StringBuffer is thread safe, StringBuilder is thread unsafe, HashTable is thread safe, and HashMap is thread unsafe
4, Summary
Although Synchronized can ensure the data security of multi-threaded shared data, if it is not used properly, the thread holds the lock object for a long time and is not released in time, it is easy to cause deadlock problems. Moreover, in terms of performance, Synchronized will also have a certain impact on performance, so please use Synchronized with caution.