1、Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”。

Java中每个对象都有一个锁,并且是唯一的。假设分配的一个对象空间,里面有多个方法,相当于空间里面有多个小房间,如果我们把所有的小房间都加锁,因为这个对象只有一把钥匙,因此同一时间只能有一个人打开一个小房间,然后用完了还回去,再由JVM 去分配下一个获得钥匙的人。


情况1:同一个对象在两个线程中分别访问该对象的两个同步方法

结果:会产生互斥。

解释:因为锁针对的是对象,当对象调用一个synchronized方法时,其他同步方法需要等待其执行结束并释放锁后才能执行。


情况2:不同对象在两个线程中调用同一个同步方法

结果:不会产生互斥。

解释:因为是两个对象,锁针对的是对象,并不是方法,所以可以并发执行,不会互斥。形象的来说就是因为我们每个线程在调用方法的时候都是new 一个对象,那么就会出现两个空间,两把钥匙,

2、Synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”。

情况1:用类直接在两个线程中调用两个不同的同步方法

结果:会产生互斥。

解释:因为对静态对象加锁实际上对类(.class)加锁,类对象只有一个,可以理解为任何时候都只有一个空间,里面有N个房间,一把锁,因此房间(同步方法)之间一定是互斥的。

:上述情况和用单例模式声明一个对象来调用非静态方法的情况是一样的,因为永远就只有这一个对象。所以访问同步方法之间一定是互斥的。


情况2:用一个类的静态对象在两个线程中调用静态方法或非静态方法

结果:会产生互斥。

解释:因为是一个对象调用,同上。


情况3:一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法

结果:不会产生互斥。

解释:因为虽然是一个对象调用,但是两个方法的锁类型不同,调用的静态方法实际上是类对象在调用,即这两个方法产生的并不是同一个对象锁,因此不会互斥,会并发执行。


我们下面来看一道题目:

pulbic class Something(){

<span >public</span> <span >synchronized</span> <span >void</span> <span >isSyncA</span><span >(</span><span >)</span><span >{</span><span >}</span>

<span >public</span> <span >synchronized</span> <span >void</span> <span >isSyncB</span><span >(</span><span >)</span><span >{</span><span >}</span>

<span >public</span> <span >static</span> <span >synchronized</span> <span >void</span> <span >cSyncA</span><span >(</span><span >)</span><span >{</span><span >}</span>

<span >public</span> <span >static</span> <span >synchronized</span> <span >void</span> <span >cSyncB</span><span >(</span><span >)</span><span >{</span><span >}</span>

}



那么,加入有Something类的两个实例a与b,那么下列哪组方法可以被1个以上线程同时访问呢?

a. x.isSyncA()与 x.isSyncB()

b. x.isSyncA()与 y.isSyncA()

c. x.cSyncA()与 y.cSyncB()

d. x.isSyncA()与 Something.cSyncA()

这里,很清楚的可以判断:

a,都是对同一个实例的synchronized域访问,因此不能被同时访问

b,是针对不同实例的,因此可以同时被访问

c,因为是static synchronized,所以不同实例之间不会被限制

d,书上的答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。


针对上面的题目,我们来写个demo验证下:

package com.concurrent.syn;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/**
• @author riemann
• @date 2019/08/11 23:40
 */
public class SynchronizedTest {
public static SynchronizedTest staticIn = new SynchronizedTest(); //静态对象
public synchronized void method1() {// 非静态方法1
for (int i = 0; i < 10; i++) {
 System.out.println(“method1 is running!”);
try {
 Thread.sleep(1000);
} catch (InterruptedException e) {
 e.printStackTrace();
}
}
}
public synchronized void method2() {// 非静态方法2
for (int i = 0; i < 10; i++) {
 System.out.println(“method2 is running!”);
try {
 Thread.sleep(1000);
} catch (InterruptedException e) {
 e.printStackTrace();
}
}
}
public synchronized static void staticMethod1() {// 静态方法1
for (int i = 0; i < 10; i++) {
 System.out.println(“staticMethod1 is running!”);
try {
 Thread.sleep(1000);
} catch (InterruptedException e) {
 e.printStackTrace();
}
}
}
public synchronized void staticMethod2() {// 静态方法2
for (int i = 0; i < 10; i++) {
 System.out.println(“staticMethod2 is running!”);
try {
 Thread.sleep(1000);
} catch (InterruptedException e) {
 e.printStackTrace();
}
}
}
static class Thread1 implements Runnable {<span class="token annotation punctuation">@Override</span>
 <span >public</span> <span >void</span> <span >run</span><span >(</span><span >)</span> <span >{</span>
     SynchronizedTest<span >.</span>staticIn<span >.</span><span >method1</span><span >(</span><span >)</span><span >;</span>
 <span >}</span>}
static class Thread2 implements Runnable {
<span class="token annotation punctuation">@Override</span>
 <span >public</span> <span >void</span> <span >run</span><span >(</span><span >)</span> <span >{</span>
     SynchronizedTest<span >.</span>staticIn<span >.</span><span >method2</span><span >(</span><span >)</span><span >;</span>
 <span >}</span>}
public static void main(String[] args) {
 Thread t1 = new Thread(new Thread1());
 Thread t2 = new Thread(new Thread2());
 ExecutorService service = Executors.newCachedThreadPool();
 service.execute(t1);
 service.execute(t2);
 service.shutdown();
}}



(1)、a. x.isSyncA()与 x.isSyncB()

thread1:SynchronizedTest.staticIn.method1();

thread2:SynchronizedTest.staticIn.method2();


  • 1
  • 2
  • 3

输出结果:

method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method1 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
method2 is running!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

从结果也可以验证出 a,都是对同一个实例的synchronized域访问,因此不能被同时访问。

(2)、b. x.isSyncA()与 y.isSyncA()

thread1:SynchronizedTest.staticIn.method1();

thread2:staticIn2.method1();


  • 1
  • 2
  • 3

我了测试效果,我在另外一个实例的方法中的打印输出做了一点微调

public synchronized void method1() {// 非静态方法1
    for (int i = 0; i < 10; i++) {
        System.out.println("method1 concurrent is running!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

输出结果:

method1 is running!
method1 concurrent is running!
method1 concurrent is running!
method1 is running!
method1 concurrent is running!
method1 is running!
method1 is running!
method1 concurrent is running!
method1 is running!
method1 concurrent is running!
method1 concurrent is running!
method1 is running!
method1 concurrent is running!
method1 is running!
method1 concurrent is running!
method1 is running!
method1 concurrent is running!
method1 is running!
method1 concurrent is running!
method1 is running!

从结果也可以验证出 b,是针对不同实例的,因此可以同时被访问。

(3)、c. x.cSyncA()与 y.cSyncB()

thread1:SynchronizedTest.staticIn.staticMethod1();

thread2:staticIn2.staticMethod2();



在另外一个类中加上方法

public synchronized void staticMethod2() {// 静态方法2
    for (int i = 0; i < 10; i++) {
        System.out.println("staticMethod2 concurrent is running!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!
staticMethod2 concurrent is running!
staticMethod1 is running!

通过结果可以验证 c,因为是static synchronized,所以不同实例之间不会被限制。

(4)、d. x.isSyncA()与y.cSyncA()

thread1:SynchronizedTest.staticIn.method2();

thread2:staticIn2.staticMethod2();


  • 1
  • 2
  • 3

输出结果:

staticMethod2 concurrent is running!
method2 is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!
method2 is running!
staticMethod2 concurrent is running!

由结果可知 synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同

</div>
            <link href="" rel="stylesheet">
                                            <div class="more-toolbox">
            <div class="left-toolbox">
                <ul class="toolbox-list">
                    
                    <li class="tool-item tool-active is-like "><a href="javascript:;"><svg class="icon" aria-hidden="true">
                        <use xlink:href="#csdnc-thumbsup"></use>
                    </svg><span class="name">点赞</span>
                    <span class="count"></span>
                    </a></li>
                    <li class="tool-item tool-active is-collection "><a href="javascript:;" data-report-click="{"mod":"popu_824"}"><svg class="icon" aria-hidden="true">
                        <use xlink:href="#icon-csdnc-Collection-G"></use>
                    </svg><span class="name">收藏</span></a></li>
                    <li class="tool-item tool-active is-share"><a href="javascript:;"><svg class="icon" aria-hidden="true">
                        <use xlink:href="#icon-csdnc-fenxiang"></use>
                    </svg>分享</a></li>
                    <!--打赏开始-->
                                            <!--打赏结束-->
                                            <li class="tool-item tool-more">
                        <a>
                        <svg t="1575545411852" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M179.176 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5718"></path><path d="M509.684 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5719"></path><path d="M846.175 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5720"></path></svg>
                        </a>
                        <ul class="more-box">
                            <li class="item"><a class="article-report">文章举报</a></li>
                        </ul>
                    </li>
                                        </ul>
            </div>
                        </div>
        <div class="person-messagebox">
            <div class="left-message"><a href="">
                <img src="" class="avatar_pic" username="riemann_">
                                        <img src="" class="user-years">
                                </a></div>
            <div class="middle-message">
                                    <div class="title"><span class="tit"><a href="" data-report-click="{"mod":"popu_379"}" target="_blank">riemann_</a></span>
                                        </div>
                <div class="text"><span>发布了364 篇原创文章</span> · <span>获赞 231</span> · <span>访问量 14万+</span></div>
            </div>
                            <div class="right-message">
                                        <a href="" target="_blank" class="btn btn-sm btn-red-hollow bt-button personal-letter">私信
                    </a>
                                                        <a class="btn btn-sm  bt-button personal-watch" data-report-click="{"mod":"popu_379"}">关注</a>
                                </div>
                        </div>
                </div>


1、Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”。

Java中每个对象都有一个锁,并且是唯一的。假设分配的一个对象空间,里面有多个方法,相当于空间里面有多个小房间,如果我们把所有的小房间都加锁,因为这个对象只有一把钥匙,因此同一时间只能有一个人打开一个小房间,然后用完了还回去,再由JVM 去分配下一个获得钥匙的人。


情况1:同一个对象在两个线程中分别访问该对象的两个同步方法

结果:会产生互斥。

解释:因为锁针对的是对象,当对象调用一个synchronized方法时,其他同步方法需要等待其执行结束并释放锁后才能执行。


情况2:不同对象在两个线程中调用同一个同步方法

结果:不会产生互斥。

解释:因为是两个对象,锁针对的是对象,并不是方法,所以可以并发执行,不会互斥。形象的来说就是因为我们每个线程在调用方法的时候都是new 一个对象,那么就会出现两个空间,两把钥匙,

2、Synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”。

情况1:用类直接在两个线程中调用两个不同的同步方法

结果:会产生互斥。

解释:因为对静态对象加锁实际上对类(.class)加锁,类对象只有一个,可以理解为任何时候都只有一个空间,里面有N个房间,一把锁,因此房间(同步方法)之间一定是互斥的。

:上述情况和用单例模式声明一个对象来调用非静态方法的情况是一样的,因为永远就只有这一个对象。所以访问同步方法之间一定是互斥的。


情况2:用一个类的静态对象在两个线程中调用静态方法或非静态方法

结果:会产生互斥。

解释:因为是一个对象调用,同上。


情况3:一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法

结果:不会产生互斥。

解释:因为虽然是一个对象调用,但是两个方法的锁类型不同,调用的静态方法实际上是类对象在调用,即这两个方法产生的并不是同一个对象锁,因此不会互斥,会并发执行。


我们下面来看一道题目:

pulbic class Something(){

<span >public</span> <span >synchronized</span> <span >void</span> <span >isSyncA</span><span >(</span><span >)</span><span >{</span><span >}</span>

<span >public</span> <span >synchronized</span> <span >void</span> <span >isSyncB</span><span >(</span><span >)</span><span >{</span><span >}</span>

<span >public</span> <span >static</span> <span >synchronized</span> <span >void</span> <span >cSyncA</span><span >(</span><span >)</span><span >{</span><span >}</span>

<span >public</span> <span >static</span> <span >synchronized</span> <span >void</span> <span >cSyncB</span><span >(</span><span >)</span><span >{</span><span >}</span>