Reference:
https://www.imooc.com/video/20418
https://stackoverflow.com/questions/1085709/what-does-synchronized-mean
The synchronized keyword causes a thread to obtain a lock when entering the method,
so that only one thread can execute the method at the same time
synchronized method: acquires the lock of that object
synchronized statements/block :
1.Every object/class has an intrinsic lock associated with it.
2.When a thread invokes a synchronized statement, it automatically acquires the intrinsic lock for that synchronized statement's object and releases it when the method returns. As long as a thread owns an intrinsic lock, NO other thread can acquire the SAME lock => thread-safe.
面试常考
面试常考关于synchronized的7种情景
1.两个线程call同一个对象的同步方法?
只有一个线程先拿到锁进去,然后执行完,释放锁,第二个线程在拿锁再进去执行
2.两个线程call两个对象的同步方法。
因为锁是两个不同的实例,两个线程会同时执行/并行
3.两个线程call一个同步静态方法。
只有一个线程先拿到锁进去,然后执行完,释放锁,第二个线程在拿锁再进去执行
4.两个线程一个访问同步方法,另一个访问非同步方法。
两个线程会同时执行/并行,非同步方法不受影响
5。call一个对象的不同的同步方法,两个线程,一个call一个同步方法,另一个访问call一个同步方法。
只有一个线程先拿到锁进去,然后执行完,释放锁,第二个线程在拿锁再进去执行(锁是这个对象本身)
6。同时call静态的同步方法和非静态的同步方法。
一个锁是当前对象,一个是当前的Class对象,所以两个线程会同时执行
7。方法抛出异常后会不会释放锁?synchronized 会vs Lock 不会。
一个线程一旦抛出了异常,捕获了以后,会继续执行,执行完以后,然后释放锁,另外一个线程会开始执行

Synchronized 关键字的性质
同一个线程内,如果该线程已经有那把锁,可以用自己拥有的那把锁进入其他的需要那把锁的方法



Code example
If No Synchronized(each run return different i)
public static void ifNoSynchronized() {
i = 0; // reset
Runnable r = () -> {
for (int j = 0;j < 10000; j++) {
i++; //contains three operation: read i, then i = i+1; write back to memory
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
//https://stackoverflow.com/questions/15956231/what-does-this-thread-join-code-mean
//t1 and t2 threads have been running in parallel
//but the main thread that started them needs to wait for them to finish before it can continue
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// each runs print different i
System.out.println("if no Synchronized:" + i);
}
Then add Synchronized(then each time will always be 20000)
public static void ifSynchronized() {
i = 0; //reset
// https://stackoverflow.com/questions/3369287/what-is-the-difference-between-synchronized-on-lockobject-and-using-this-as-the
// lock with empty Object instead of this
Object lock = new Object();
Runnable r = () -> {
//The synchronized keyword causes a thread to obtain a lock when entering the method,
//so that only one thread can execute the method at the same time
//synchronized method : acquires the lock of that object
/*
synchronized statements/block :
Every object/class have an intrinsic lock associated with it.
When a thread invokes a synchronized statement, it automatically acquires the intrinsic lock for that synchronized statement's object and releases it when the method returns. As long as a thread owns an intrinsic lock, NO other thread can acquire the SAME lock => thread safe.
*/
synchronized (lock) {
for (int j = 0;j < 10000; j++) {
i++; //contains three operation: read i, then i = i+1; write back to memory
}
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
//https://stackoverflow.com/questions/15956231/what-does-this-thread-join-code-mean
//t1 and t2 threads have been running in parallel
//but the main thread that started them needs to wait for them to finish before it can continue
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// each runs print different i
System.out.println("if Synchronized:" + i);
}
Lock on same & different object
public static void ifSynchronizedOnSameLock() {
Object lock = new Object();
Runnable r = () -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " will sleep");
try {
Thread.sleep(2000);//during the sleep, lock was hold, so other thread for this lock can't execute
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up");
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void ifSynchronizedOnDifferentLock() {
Runnable r = () -> {
// lock on different object, then two thread will execute at same time
Object lock = new Object();
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " will sleep");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up");
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
两个线程一个执行某对象的一个synchronized方法,一个执行某对象的另外一个synchronized方法
执行结果:只有一个线程先拿到锁进去,然后执行完,释放锁,第二个线程在拿锁再进去执行(锁是这个对象本身)
然后遇到synchronized方法抛出异常的情况,异常捕获后,接着执行完当前synchronized方法,释放锁
public static void sameObjectDifferentSynchronizedMethod() {
SynchronizedTest st = new SynchronizedTest();
Runnable r1 = () -> {
st.test1();
};
Runnable r2 = () -> {
st.test2();
};
Thread t1 = new Thread( r1 );
Thread t2 = new Thread( r2 );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//https://www.imooc.com/video/18614
public static void synchronizedWithException() {
SynchronizedTest st = new SynchronizedTest();
Runnable r3 = () -> {
st.test3();
};
Runnable r2 = () -> {
st.test2();
};
Thread t1 = new Thread( r3 );
Thread t2 = new Thread( r2 );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void test1() {
System.out.println(Thread.currentThread().getName() + " will sleep:test1");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up:test1");
}
public synchronized void test2() {
System.out.println(Thread.currentThread().getName() + " will sleep:test2");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up:test2");
}
public synchronized void test3() {
System.out.println(Thread.currentThread().getName() + " will sleep:test3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " running:test3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " done: test3");
}
Whole Source Code:
//https://www.imooc.com/video/20418
public class SynchronizedTest {
static int i = 0;
public static void main(String[] args) {
// SynchronizedTest.ifNoSynchronized();
// SynchronizedTest.ifSynchronized();
// SynchronizedTest.ifSynchronizedOnSameLock();
// SynchronizedTest.ifSynchronizedOnDifferentLock();
// SynchronizedTest.sameObjectDifferentSynchronizedMethod();
SynchronizedTest.synchronizedWithException();
}
public static void ifNoSynchronized() {
i = 0; // reset
Runnable r = () -> {
for (int j = 0;j < 10000; j++) {
i++; //contains three operation: read i, then i = i+1; write back to memory
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
//https://stackoverflow.com/questions/15956231/what-does-this-thread-join-code-mean
//t1 and t2 threads have been running in parallel
//but the main thread that started them needs to wait for them to finish before it can continue
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// each runs print different i
System.out.println("if no Synchronized:" + i);
}
public static void ifSynchronized() {
i = 0; //reset
// https://stackoverflow.com/questions/3369287/what-is-the-difference-between-synchronized-on-lockobject-and-using-this-as-the
// lock with empty Object instead of this
Object lock = new Object();
Runnable r = () -> {
//The synchronized keyword causes a thread to obtain a lock when entering the method,
//so that only one thread can execute the method at the same time
//synchronized method : acquires the lock of that object
/*
synchronized statements/block :
Every object/class have an intrinsic lock associated with it.
When a thread invokes a synchronized statement, it automatically acquires the intrinsic lock for that synchronized statement's object and releases it when the method returns. As long as a thread owns an intrinsic lock, NO other thread can acquire the SAME lock => thread safe.
*/
synchronized (lock) {
for (int j = 0;j < 10000; j++) {
i++; //contains three operation: read i, then i = i+1; write back to memory
}
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
//https://stackoverflow.com/questions/15956231/what-does-this-thread-join-code-mean
//t1 and t2 threads have been running in parallel
//but the main thread that started them needs to wait for them to finish before it can continue
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// each runs print different i
System.out.println("if Synchronized:" + i);
}
public static void ifSynchronizedOnSameLock() {
Object lock = new Object();
Runnable r = () -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " will sleep");
try {
Thread.sleep(2000);//during the sleep, lock was hold, so other thread for this lock can't execute
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up");
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void ifSynchronizedOnDifferentLock() {
Runnable r = () -> {
// lock on different object, then two thread will execute at same time
Object lock = new Object();
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " will sleep");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up");
}
};
Thread t1 = new Thread( r );
Thread t2 = new Thread( r );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 面试常考关于synchronized的7种情景
// 1.两个线程call同一个对象的同步方法?
// 只有一个线程先拿到锁进去,然后执行完,释放锁,第二个线程在拿锁再进去执行
// 2.两个线程call两个对象的同步方法。
// 因为锁是两个不同的实例,两个线程会同时执行/并行
// 3.两个线程call一个同步静态方法。
// 只有一个线程先拿到锁进去,然后执行完,释放锁,第二个线程在拿锁再进去执行
// 4.两个线程一个访问同步方法,另一个访问非同步方法。
// 两个线程会同时执行/并行,非同步方法不受影响
// 5。call一个对象的不同的同步方法,两个线程,一个call一个同步方法,另一个访问call一个同步方法。
// 只有一个线程先拿到锁进去,然后执行完,释放锁,第二个线程在拿锁再进去执行(锁是这个对象本身)
// 6。同时call静态的同步方法和非静态的同步方法。
// 一个锁是当前对象,一个是当前的Class对象,所以两个线程会同时执行
// 7。方法抛出异常后会不会释放锁?synchronized 会vs Lock 不会。
// 一个线程一旦抛出了异常,捕获了以后,会继续执行,执行完以后,然后释放锁,另外一个线程会开始执行
public static void sameObjectDifferentSynchronizedMethod() {
SynchronizedTest st = new SynchronizedTest();
Runnable r1 = () -> {
st.test1();
};
Runnable r2 = () -> {
st.test2();
};
Thread t1 = new Thread( r1 );
Thread t2 = new Thread( r2 );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//https://www.imooc.com/video/18614
public static void synchronizedWithException() {
SynchronizedTest st = new SynchronizedTest();
Runnable r3 = () -> {
st.test3();
};
Runnable r2 = () -> {
st.test2();
};
Thread t1 = new Thread( r3 );
Thread t2 = new Thread( r2 );
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void test1() {
System.out.println(Thread.currentThread().getName() + " will sleep:test1");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up:test1");
}
public synchronized void test2() {
System.out.println(Thread.currentThread().getName() + " will sleep:test2");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wake up:test2");
}
public synchronized void test3() {
System.out.println(Thread.currentThread().getName() + " will sleep:test3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " running:test3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " done: test3");
}
}