Synchronized 关键字的用法
第一条:当一个线程访问某对象的synchronized方法或者synchronized代码块时,其他线程对该对象的该synchronized方法或者synchronized代码块的访问将被阻塞。
public class MoreThread { public static void main(String[] args) { Piao piao = new Piao(); Thread t1 = new Thread(piao); Thread t2 = new Thread(piao); Thread t3 = new Thread(piao); t1.start(); t2.start(); t3.start(); } } class Piao implements Runnable { @Override public void run() { /*synchronized(this) {*/ for (int i = 0; i < 10; i++) { try { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + " 卖票:ticket " + i); } catch (InterruptedException e) { e.printStackTrace(); } } /*}*/ } }
没有加上synchronized:
Thread-1 卖票:ticket 0 Thread-0 卖票:ticket 0 Thread-2 卖票:ticket 0 Thread-1 卖票:ticket 1 Thread-0 卖票:ticket 1 Thread-2 卖票:ticket 1 Thread-1 卖票:ticket 2 Thread-0 卖票:ticket 2 Thread-2 卖票:ticket 2 Thread-1 卖票:ticket 3 Thread-0 卖票:ticket 3 Thread-2 卖票:ticket 3 Thread-0 卖票:ticket 4 Thread-2 卖票:ticket 4 Thread-1 卖票:ticket 4 Thread-2 卖票:ticket 5 Thread-0 卖票:ticket 5 Thread-1 卖票:ticket 5 Thread-1 卖票:ticket 6 Thread-2 卖票:ticket 6 Thread-0 卖票:ticket 6 Thread-1 卖票:ticket 7 Thread-0 卖票:ticket 7 Thread-2 卖票:ticket 7 Thread-1 卖票:ticket 8 Thread-0 卖票:ticket 8 Thread-2 卖票:ticket 8 Thread-1 卖票:ticket 9 Thread-2 卖票:ticket 9 Thread-0 卖票:ticket 9
加上synchronized:这个代码块要等一个线程访问完成之后,另一个线程才能访问。
Thread-1 卖票:ticket 0 Thread-1 卖票:ticket 1 Thread-1 卖票:ticket 2 Thread-1 卖票:ticket 3 Thread-1 卖票:ticket 4 Thread-1 卖票:ticket 5 Thread-1 卖票:ticket 6 Thread-1 卖票:ticket 7 Thread-1 卖票:ticket 8 Thread-1 卖票:ticket 9 Thread-0 卖票:ticket 0 Thread-0 卖票:ticket 1 Thread-0 卖票:ticket 2 Thread-0 卖票:ticket 3 Thread-0 卖票:ticket 4 Thread-0 卖票:ticket 5 Thread-0 卖票:ticket 6 Thread-0 卖票:ticket 7 Thread-0 卖票:ticket 8 Thread-0 卖票:ticket 9 Thread-2 卖票:ticket 0 Thread-2 卖票:ticket 1 Thread-2 卖票:ticket 2 Thread-2 卖票:ticket 3 Thread-2 卖票:ticket 4 Thread-2 卖票:ticket 5 Thread-2 卖票:ticket 6 Thread-2 卖票:ticket 7 Thread-2 卖票:ticket 8 Thread-2 卖票:ticket 9
第二条:当一个线程访问某对象的synchronized方法或者synchronized代码块时,其他线程仍然可以访问该对象的非同步代码块。
1 public class MoreThread { 2 public static void main(String[] args) { 3 TestSynchronized t = new TestSynchronized(); 4 Thread t1 = new Thread(() -> t.SynMethod()); 5 Thread t2 = new Thread(() -> t.NoSynMethod()); 6 7 t1.start(); 8 t2.start(); 9 } 10 11 } 12 class TestSynchronized { 13 14 public void SynMethod() { 15 synchronized (this) { 16 try { 17 for (int i = 0; i < 5; i++) { 18 Thread.sleep(1000); // 休眠100ms 19 System.out.println(Thread.currentThread().getName() + " synMethod loop " + i); 20 } 21 } catch (InterruptedException ie) { 22 } 23 } 24 } 25 26 public void NoSynMethod() { 27 synchronized (this) { 28 try { 29 for (int i = 0; i < 5; i++) { 30 Thread.sleep(1000); // 休眠100ms 31 System.out.println(Thread.currentThread().getName() + " synMethod loop " + i); 32 } 33 } catch (InterruptedException e) { 34 e.printStackTrace(); 35 } 36 } 37 }
当线程 t1去调用含有synchronized()的时候,会获取到对象的同步锁(每一个对象有且只有一个同步锁)。此时线程 t2 可以去调用没有synchronized修饰的代码块。不会发生阻塞。执行结果会交叉执行
1 Thread-0 synMethod loop 0 2 Thread-1 synMethod loop 0 3 Thread-0 synMethod loop 1 4 Thread-1 synMethod loop 1 5 Thread-0 synMethod loop 2 6 Thread-1 synMethod loop 2 7 Thread-1 synMethod loop 3 8 Thread-0 synMethod loop 3 9 Thread-1 synMethod loop 4 10 Thread-0 synMethod loop 4 11 12 Process finished with exit code 0
如果给方法中加上synchroniezd(this) 那么线程t2在执行的时候会发生阻塞。会等一个线程执行完后,释放锁后,另一线程才会运行
1 Thread-1 synMethod loop 0 2 Thread-1 synMethod loop 1 3 Thread-1 synMethod loop 2 4 Thread-1 synMethod loop 3 5 Thread-1 synMethod loop 4 6 Thread-0 synMethod loop 0 7 Thread-0 synMethod loop 1 8 Thread-0 synMethod loop 2 9 Thread-0 synMethod loop 3 10 Thread-0 synMethod loop 4 11 12 Process finished with exit code 0
第三条:当一个线程访问某对象的synchronized方法或者synchronized代码块时,其他线程对该对象的其他的synchronized方法或者synchronized代码块的访问将被阻塞。
from:https://blog.csdn.net/wanliguodu/article/details/81005560