synchronized 是什么?
老王:小陈,从今天开始我们就要进入synchronized的讨论了;首先小陈你来讲讲对synchronized的理解
小陈:synchronized啊,我理解就是一个JDK提供的同步的关键字,通过synchronized可以锁定一个代码块或者一个方法,从而实现锁的效果。
通过synchronized锁定的代码块或者方法同一时间只能由一个线程去执行,等这个线程执行完了释放锁了之后别的线程才能获取锁进入并且执行。
老王:那你说说synchronized的几种用法?
小陈:嘿嘿,这还不简单
synchronized的几种用法
(1)修饰在对象方法上:
public class SynDemo { int i = 0; int x = 0; public synchronized void testSync() { i++; x++; } }
放在实例方法上的时候,锁住的是这个SyncDemo的实例对象。
(2)修饰在静态方法上:
public class SynDemo { static int value = 0; public synchronized static void testStaticSync() { value++; } }
修饰在静态方法上的时候,锁的是这个类对应的类对象,也就是SyncDemo.class对象
(3)在方法内部的同步代码块:
public class SynDemo { int i = 0; int x = 0; Object lockObj = new Object(); public void testInnerSync() { synchronized(lockObj) { i++; x++; } } }
像这种方式,锁住其实就是lockObj这个对象。
小陈:老王,synchronized使用的三种方式我讲完了
synchronized注意事项
老王:既然你都知道使用的几种方式了,那么使用synchronized关键字需要注意的是什么?
小陈:其实synchronized是对一个对象上锁的,使用的时候需要注意在对同一个对象上锁才能达到互斥的目的。
我直接上代码来讲解一下吧:
(1)定义一个TestThread类,继承自Thread
(2)TestThread的内部持有一个SycDemo对象
(3)TestThread的run方法内部调用SyncDemo对象的testSync方法执行synchronized修饰的同步方法。
public class SynDemo { int i = 0; int x = 0; // 争抢对象SyncDemo的锁 public synchronized void testSync() { i++; x++; } static class TestThread extends Thread { SynDemo lock; TestThread(SynDemo lock) { this.lock = lock; } @Override public void run() { lock.testSync(); } } public static void main(String[] args) { // 锁对象lock1 SynDemo lock1 = new SynDemo(); // 锁对象lock2 SynDemo lock2 = new SynDemo(); TestThread threadA = new TestThread(lock1); TestThread threadB = new TestThread(lock2); threadA.start(); threadB.start(); } }
像这种方式,threadA和threadB是达不到互斥的目的的,因为threadA锁住的是lock1对象;然而thread锁住的是lock2对象。完全争抢的不是同一个锁。
老王:那如果要使得threadA和threadB达到同步的目的,应该怎么做?
小陈:需要threadA和threadB争抢同一把锁,争抢同一个同一个对象的锁才可以,也就是像下面那样,也就是threadA和threadB都使用同一对象锁ock1,这样才是正确的:
public static void main(String[] args) { // 只有一个锁对象lock1 SynDemo lock1 = new SynDemo(); // 两个线程对同一个对象锁进行争抢 TestThread threadA = new TestThread(lock1); TestThread threadB = new TestThread(lock1); threadA.start(); threadB.start(); }
小陈:对于synchronized修饰static的方法,synchronized锁的是这个类对象,由于类对象只有一个,所以不同线程同时通过类调用这个方法的时候就能互斥的效果。
老王:嗯嗯,看来synchronized的使用方式、注意事项你都基本理解了;下面我们就来深入一点,开始探索synchronized的底层的实现原理了....
小陈:嘿嘿,终于可以进入原理级别去理解synchronized了......
老王:下一篇 《对象头、Mark Word、monitor、synchronized怎么关联起来?》 你别错过哦....
小陈:好的,老王,我们下一章见。