Start with no synchronized
Look at the following code
public class StatefulTest {
public static void main(String[] args) {
Runnable stateOfX = () ->{// Implement the Runnable interface
/* Member variables are shared by multiple threads. An object is said to be stateful if it has modifiable member variables. Conversely, if it has no modifiable member variables, it is called stateless */
int x = 0;
while(x! =40){
System.out.println("x: "+x++);
try {
Thread.sleep((long) (Math.random()*100));
} catch(InterruptedException e) { e.printStackTrace(); }}};// Access stateOfX through two threads simultaneously
new Thread(stateOfX).start();
newThread(stateOfX).start(); }}Copy the code
- The results
- It turns out that
- Both threads get x = 0 at the same time, indicating that x can be shared by multiple threads
- The same number only appears twice
- One thread modifies the value, and other threads get the changed value
Use synchronized
code
- Create an instance object
public class HelloAndWorld {
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
Runnable run1 = test::hello;// Reference the instance method of test
Runnable run2 = test::world;
new Thread(run1).start();
Thread.sleep((long) (Math.random() * 200));// Thread sleep, run1 must start execution first
newThread(run2).start(); }}class Test{// Synchronized
public synchronized void hello(a) {
try {
Thread.sleep((long) (Math.random()*1000));
System.out.println("hello");
} catch(InterruptedException e) { e.printStackTrace(); }}public synchronized void world(a){
System.out.println("world"); }}Copy the code
- Create two instance objects
public class HelloAndWorld {
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
Test test2 = new Test();// Create two real objects
Runnable run1 = test::hello;
Runnable run2 = test2::world;// The method that references the second real object
new Thread(run1).start();
Thread.sleep((long) (Math.random() * 200));// Thread sleep, run1 must start execution first
newThread(run2).start(); }}class Test{
public synchronized void hello(a) {
try {
Thread.sleep((long) (Math.random()*1000));
System.out.println("hello");
} catch(InterruptedException e) { e.printStackTrace(); }}public synchronized void world(a){
System.out.println("world"); }}Copy the code
The above two examples want to illustrate
- A thread is executing one of the real objects
synchronized
Method, another threadYou can’t execute itExecuting without threadssynchronized
methods- When a thread executes into synchronized, it acquies the lock on the object, and another thread cannot execute any other method that is modified by synchronized, regardless of whether the thread that acquired the lock on the current object is executing that method
- When a threadaftera
synchronized
Method, which must release the lock to give another thread a chance to acquire the lock on the current instance object - A thread is executing one of the real objects
synchronized
Method, another threadAnother instance object can be executedthesynchronized
methods- Different instance objects have different locks, that is, one instance object has one lock
- It is worth mentioning that.
synchronized static
Methods belong toClass
Object, does not belong to the instance object and its lock has to be counted separately
Analyze the synchronized keyword from a bytecode perspective
Example 1: when decorating a block of code
public class MyTest {
Object object = new Object();
public void method(a){
synchronized (object){
System.out.println("hello world"); }}}Copy the code
- with
Javap
Look at the bytecode instructions
- summary
- with
synchronized
When you use a keyword to modify a block of code, the instance object in parentheses can be any object, provided that the existing object, whatever object you put in parentheses, will not be affected by the block of code that will be synchronized, okay- with
synchronized
A keyword modifies a code block when it is amonitorenter
Corresponding to the twomonitorexit
Because one is used to let the thread release the lock when the block ends normally and one is used to let the thread release the lock when the block ends abnormally
Example 2: Manually throw an exception to the synchronized code block
- Example 1
monitorenter
Corresponding to the twomonitorexit
One of themmonitorexit
To prepare for the release of the lock if the block ends abnormally - Try actively throwing an exception from a synchronized block
public class MyTest {
Object object = new Object();
public void method2(a){
synchronized (object){
System.out.println("hello world");
throw new RuntimeException();// Throw an exception}}}Copy the code
- The bytecode
- summary
- Example 1: The lock release mode has two possibilities: abnormal end and normal end, so there are two
monitorexit
- In example 2, there is only one way to release the lock: to throw an exception (exception terminating) to release the lock, so there is only one
monitorexit
- In any case, the system will try to get the thread to release the lock on the object
Synchronized, synchronized, synchronized
public class MyTest {
public synchronized void method3(a){
System.out.println("hello world"); }}Copy the code
- The bytecode
- summary
- For the synchronized keyword modification method, instead of monitorenter and monitorexit directives, an ACC_SYNCHRONIZED flag appears.
- The JVM uses the ACC_SYNCHRONIZBD access flag to distinguish whether a method is synchronous; When a method is called, the calling instruction checks whether the method has the ACC_SYNCHRONIZBD flag.
- If you have
ACC_SYNCHRONIZBD
Flag, then the executing thread will first hold the object on which the method residesMonitor
, and then execute the method body. No other thread can get it during the execution of the methodMonitor
When the thread finishes executing the method, it will release thisMonitor
In other words, the lock is released as soon as the method executes (Monitor
)
Synchronized static = synchronized static = synchronized
public class MyTest {
public synchronized static void method4(a){
System.out.println("hello world"); }}Copy the code
- The bytecode
- summary
- Similar to example 3, I will not repeat it