博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
synchronized(this)与synchronized(class)
阅读量:6247 次
发布时间:2019-06-22

本文共 3046 字,大约阅读时间需要 10 分钟。

本文转自:

RunnableTest.java:

/** *  */package concurrency;/** * @author xuanyin *  */public class RunnableTest implements Runnable {    /**     *      */    private static boolean flag = true;    /**     * 使用synchronized方法     */    private static synchronized void testSyncMethod() { // 注意static        for (int i = 0; i < 100; i++) {            System.out.println("testSyncMethod:" + i);        }    }    /**     * 使用synchronized代码块     */    private void testSyncBlock() {        synchronized (this) { // 注意this            for (int i = 0; i < 100; i++) {                System.out.println("testSyncBlock:" + i);            }        }    }    /**     *      */    @Override    public void run() {        // 每个线程执行不同的方法        if (flag) {            flag = false;            testSyncMethod();        } else {            flag = true;            testSyncBlock();        }    }}

RunnableMain.java:

 

/** *  */package concurrency;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * @author xuanyin *  */public class RunnableMain {    /**     * @param args     */    public static void main(String[] args) {        ExecutorService exec = Executors.newFixedThreadPool(2);        exec.execute(new RunnableTest());        exec.execute(new RunnableTest());        exec.shutdown();    }}

 

执行RunnableMain.java后,输出结果(挑出其中一段):

...

testSyncBlock:79
testSyncMethod:89
testSyncBlock:80
testSyncMethod:90
testSyncBlock:81
testSyncMethod:91
...

可见两个线程可以同时并发执行,各自循环输出0-99。

若将RunnableTest.java中的testSyncBlock()方法改为:

 

...    /**     * 使用synchronized代码块     */    private void testSyncBlock() {        synchronized (RunnableTest.class) { // 注意由this改为RunnableTest.class,只改了此处            for (int i = 0; i < 100; i++) {                System.out.println("testSyncBlock:" + i);            }        }    }...

 

再次执行RunnableMain.java后,输出结果(挑出其中一段):

...

testSyncMethod:97
testSyncMethod:98
testSyncMethod:99
testSyncBlock:0
testSyncBlock:1
testSyncBlock:2
...

可见一个线程完成循环输出0-99后,另一个线程才从0开始。

 

接着来讲讲原理 —— 

 

Java语法规定,任何线程执行同步方法(如上例testSyncMethod是同步方法)、同步代码块(如上例testSyncBlock方法中即是同步代码块)之前,必须先获取对应的监视器

对于上例而言:

testSyncBlock方法中同步代码块的监视器是this,即调用该方法的引用对象;

testSyncMethod方法因为加了static关键字,故它的监视器不是this,而是该类本身。

所以最初的程序,因为没有使用同一个监视器,也就可以同时并发执行,两个线程各自输出0-99;

而修改后的程序,因为都是用类的本身做为监视器,所以第一个线程可以对RunnableTest类进行锁定,而第二个线程要开始必须等第一个线程执行结束后才能执行。

 

假设把testSyncMethod方法,从现在的同步方法也改成同步代码块:

...    /**     * 也改成了synchronized代码块     */    private void testSyncMethod() { // 注意没有了static synchronized        synchronized (RunnableTest.class) { // 也改成了同步代码块方式            for (int i = 0; i < 100; i++) {                System.out.println("testSyncMethod:" + i);            }        }    }    /**     * 使用synchronized代码块     */    private void testSyncBlock() {        synchronized (RunnableTest.class) { // 注意是RunnableTest.class            for (int i = 0; i < 100; i++) {                System.out.println("testSyncBlock:" + i);            }        }    }...

上例中虽然两个方法都改成了同步代码块的方式,但只要用的仍然是同一个监视器,那么就无法实现并发执行的结果,和用同步方法或同步代码块的哪种写法无关。

 

转载于:https://www.cnblogs.com/wyhailjn/p/4382505.html

你可能感兴趣的文章
[javaSE] GUI(事件监听机制)
查看>>
Electron 不完全快速手册
查看>>
[osx] intellij-idea快捷键大全
查看>>
Mac下安装MySQL(Mac 10.12)
查看>>
css 温故而知新 select-option 文字方向居右
查看>>
HTTP协议基础
查看>>
IIS发布的网站常见的问题汇总
查看>>
40岁应该学会的是面对和取舍
查看>>
UVA 12493 Stars (欧拉函数--求1~n与n互质的个数)
查看>>
PHP高级教程-异常处理(Exception)
查看>>
2017年第六届数学中国数学建模国际赛(小美赛)比赛心得
查看>>
6.C#知识点:反射
查看>>
CXF2.7整合spring发布webservice
查看>>
神经网络优化(三) - 全连接网络基础
查看>>
整形越界,死循环,产生莫名其妙的问题
查看>>
帝国cms支持的变量及灵动标签变量汇总
查看>>
【博客园客户端】博客园Android客户端更新:离线下载、本地收藏、RSS阅读
查看>>
here is the code for MJPG video capture on ip camera
查看>>
python urllib2 (转)
查看>>
[原]浅谈几种服务器端模型——反应堆模式(基于epoll的反应堆)
查看>>