2.1.4synchronized方法与锁对象

为了证明线程锁的是对象

测试

 1 package com.cky.bean;
 2 
 3 /**
 4  * Created by chenkaiyang on 2017/12/4.
 5  */
 6 public class MyObject {
 7     public void methodA () {
 8         try {
 9             System.out.println("begin methodA ThName=" +Thread.currentThread().getName());
10             Thread.sleep(5000);
11             System.out.println("end");
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         }
15     }
16 }
 1 package com.cky.thread;
 2 
 3 import com.cky.bean.MyObject;
 4 
 5 /**
 6  * Created by chenkaiyang on 2017/12/4.
 7  */
 8 public class ThreadA  extends Thread{
 9     private MyObject mo;
10     public ThreadA (MyObject mo) {
11         this.mo = mo;
12     }
13     @Override
14     public void run() {
15         super.run();
16         mo.methodA();
17     }
18 }
package com.cky.thread;

import com.cky.bean.MyObject;

/**
 * Created by chenkaiyang on 2017/12/4.
 */
public class ThreadB extends Thread{
    private MyObject mo;
    public ThreadB (MyObject mo) {
        this.mo = mo;
    }
    @Override
    public void run() {
        super.run();
        mo.methodA();
    }
}
package com.cky.test;

import com.cky.bean.MyObject;
import com.cky.thread.ThreadA;
import com.cky.thread.ThreadB;

/**
 * Created by chenkaiyang on 2017/12/2.
 */
public class Test {
    public static void main(String[] args){
        MyObject myObject = new MyObject();
        ThreadA threadA = new ThreadA(myObject);
        threadA.setName("A");
        ThreadB threadB = new ThreadB(myObject);
        threadB.setName("B");
        threadA.start();
        threadB.start();
    }
}
D:itjdk1.8injava -Didea.launcher.port=7533 "-Didea.launcher.bin.path=D:itideaIntelliJ IDEA 2016.3.3in" -Dfile.encoding=UTF-8 -classpath "D:itjdk1.8jrelibcharsets.jar;D:itjdk1.8jrelibdeploy.jar;D:itjdk1.8jrelibextaccess-bridge-64.jar;D:itjdk1.8jrelibextcldrdata.jar;D:itjdk1.8jrelibextdnsns.jar;D:itjdk1.8jrelibextjaccess.jar;D:itjdk1.8jrelibextjfxrt.jar;D:itjdk1.8jrelibextlocaledata.jar;D:itjdk1.8jrelibext
ashorn.jar;D:itjdk1.8jrelibextsunec.jar;D:itjdk1.8jrelibextsunjce_provider.jar;D:itjdk1.8jrelibextsunmscapi.jar;D:itjdk1.8jrelibextsunpkcs11.jar;D:itjdk1.8jrelibextzipfs.jar;D:itjdk1.8jrelibjavaws.jar;D:itjdk1.8jrelibjce.jar;D:itjdk1.8jrelibjfr.jar;D:itjdk1.8jrelibjfxswt.jar;D:itjdk1.8jrelibjsse.jar;D:itjdk1.8jrelibmanagement-agent.jar;D:itjdk1.8jrelibplugin.jar;D:itjdk1.8jrelib
esources.jar;D:itjdk1.8jrelib
t.jar;F:springboot	hreaddemooutproduction	hreaddemo;D:itideaIntelliJ IDEA 2016.3.3libidea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test
begin methodA ThName=A
begin methodA ThName=B
end
end

结果如上分析,代码调用是异步随机执行。

然后在方法中加同步关键字

package com.cky.bean;

/**
 * Created by chenkaiyang on 2017/12/4.
 */
public class MyObject {
    synchronized  public void methodA () {
        try {
            System.out.println("begin methodA ThName=" +Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
D:itjdk1.8injava -Didea.launcher.port=7534 "-Didea.launcher.bin.path=D:itideaIntelliJ IDEA 2016.3.3in" -Dfile.encoding=UTF-8 -classpath "D:itjdk1.8jrelibcharsets.jar;D:itjdk1.8jrelibdeploy.jar;D:itjdk1.8jrelibextaccess-bridge-64.jar;D:itjdk1.8jrelibextcldrdata.jar;D:itjdk1.8jrelibextdnsns.jar;D:itjdk1.8jrelibextjaccess.jar;D:itjdk1.8jrelibextjfxrt.jar;D:itjdk1.8jrelibextlocaledata.jar;D:itjdk1.8jrelibext
ashorn.jar;D:itjdk1.8jrelibextsunec.jar;D:itjdk1.8jrelibextsunjce_provider.jar;D:itjdk1.8jrelibextsunmscapi.jar;D:itjdk1.8jrelibextsunpkcs11.jar;D:itjdk1.8jrelibextzipfs.jar;D:itjdk1.8jrelibjavaws.jar;D:itjdk1.8jrelibjce.jar;D:itjdk1.8jrelibjfr.jar;D:itjdk1.8jrelibjfxswt.jar;D:itjdk1.8jrelibjsse.jar;D:itjdk1.8jrelibmanagement-agent.jar;D:itjdk1.8jrelibplugin.jar;D:itjdk1.8jrelib
esources.jar;D:itjdk1.8jrelib
t.jar;F:springboot	hreaddemooutproduction	hreaddemo;D:itideaIntelliJ IDEA 2016.3.3libidea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test
begin methodA ThName=A
end
begin methodA ThName=B
end

结果分析:

调用关键字synchronized声明的方法一定是排队运行的,只有共享的资源才需要同步,如果不是共享的资源,根本没有必要同步。

那如果其他的方法被调用会有什么效果。

测试

继续更改MyObject

package com.cky.bean;

/**
 * Created by chenkaiyang on 2017/12/4.
 */
public class MyObject {
    synchronized  public void methodA () {
        try {
            System.out.println("begin methodA ThName=" +Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void methodB() {
        try {
            System.out.println("begin methodB ThName=" +Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.cky.thread;

import com.cky.bean.MyObject;

/**
 * Created by chenkaiyang on 2017/12/4.
 */
public class ThreadA  extends Thread{
    private MyObject mo;
    public ThreadA (MyObject mo) {
        this.mo = mo;
    }
    @Override
    public void run() {
        super.run();
        mo.methodA();
    }
}
package com.cky.thread;

import com.cky.bean.MyObject;

/**
 * Created by chenkaiyang on 2017/12/4.
 */
public class ThreadB extends Thread{
    private MyObject mo;
    public ThreadB (MyObject mo) {
        this.mo = mo;
    }
    @Override
    public void run() {
        super.run();
        mo.methodB();
    }
}
package com.cky.test;

import com.cky.bean.MyObject;
import com.cky.thread.ThreadA;
import com.cky.thread.ThreadB;

/**
 * Created by chenkaiyang on 2017/12/2.
 */
public class Test {
    public static void main(String[] args){
        MyObject myObject = new MyObject();
        ThreadA threadA = new ThreadA(myObject);
        threadA.setName("A");
        ThreadB threadB = new ThreadB(myObject);
        threadB.setName("B");
        threadA.start();
        threadB.start();
    }
}
D:itjdk1.8injava -Didea.launcher.port=7536 "-Didea.launcher.bin.path=D:itideaIntelliJ IDEA 2016.3.3in" -Dfile.encoding=UTF-8 -classpath "D:itjdk1.8jrelibcharsets.jar;D:itjdk1.8jrelibdeploy.jar;D:itjdk1.8jrelibextaccess-bridge-64.jar;D:itjdk1.8jrelibextcldrdata.jar;D:itjdk1.8jrelibextdnsns.jar;D:itjdk1.8jrelibextjaccess.jar;D:itjdk1.8jrelibextjfxrt.jar;D:itjdk1.8jrelibextlocaledata.jar;D:itjdk1.8jrelibext
ashorn.jar;D:itjdk1.8jrelibextsunec.jar;D:itjdk1.8jrelibextsunjce_provider.jar;D:itjdk1.8jrelibextsunmscapi.jar;D:itjdk1.8jrelibextsunpkcs11.jar;D:itjdk1.8jrelibextzipfs.jar;D:itjdk1.8jrelibjavaws.jar;D:itjdk1.8jrelibjce.jar;D:itjdk1.8jrelibjfr.jar;D:itjdk1.8jrelibjfxswt.jar;D:itjdk1.8jrelibjsse.jar;D:itjdk1.8jrelibmanagement-agent.jar;D:itjdk1.8jrelibplugin.jar;D:itjdk1.8jrelib
esources.jar;D:itjdk1.8jrelib
t.jar;F:springboot	hreaddemooutproduction	hreaddemo;D:itideaIntelliJ IDEA 2016.3.3libidea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test
begin methodA ThName=A
begin methodB ThName=B
end
end

结果分析:虽然线程A先持有object对象的锁,但是线程B完全可以异步调用非synchronized类型的方法。

继续再methodB方法上加上synchronized

package com.cky.bean;

/**
 * Created by chenkaiyang on 2017/12/4.
 */
public class MyObject {
    synchronized  public void methodA () {
        try {
            System.out.println("begin methodA ThName=" +Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
   synchronized public void methodB() {
        try {
            System.out.println("begin methodB ThName=" +Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
D:itjdk1.8injava -Didea.launcher.port=7537 "-Didea.launcher.bin.path=D:itideaIntelliJ IDEA 2016.3.3in" -Dfile.encoding=UTF-8 -classpath "D:itjdk1.8jrelibcharsets.jar;D:itjdk1.8jrelibdeploy.jar;D:itjdk1.8jrelibextaccess-bridge-64.jar;D:itjdk1.8jrelibextcldrdata.jar;D:itjdk1.8jrelibextdnsns.jar;D:itjdk1.8jrelibextjaccess.jar;D:itjdk1.8jrelibextjfxrt.jar;D:itjdk1.8jrelibextlocaledata.jar;D:itjdk1.8jrelibext
ashorn.jar;D:itjdk1.8jrelibextsunec.jar;D:itjdk1.8jrelibextsunjce_provider.jar;D:itjdk1.8jrelibextsunmscapi.jar;D:itjdk1.8jrelibextsunpkcs11.jar;D:itjdk1.8jrelibextzipfs.jar;D:itjdk1.8jrelibjavaws.jar;D:itjdk1.8jrelibjce.jar;D:itjdk1.8jrelibjfr.jar;D:itjdk1.8jrelibjfxswt.jar;D:itjdk1.8jrelibjsse.jar;D:itjdk1.8jrelibmanagement-agent.jar;D:itjdk1.8jrelibplugin.jar;D:itjdk1.8jrelib
esources.jar;D:itjdk1.8jrelib
t.jar;F:springboot	hreaddemooutproduction	hreaddemo;D:itideaIntelliJ IDEA 2016.3.3libidea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test
begin methodB ThName=B
end
begin methodA ThName=A
end

Process finished with exit code 0

结果分析:

1)A线程先持有对象锁,B线程可以异步方法调用object对象中非同步的方法

2)A线程先持有对象锁,B线程此时如果想要调用B线程中其他的同步方法,则需要等待A线程释放才行

原文地址:https://www.cnblogs.com/edison20161121/p/7967429.html