博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java线程安全synchronize学习
阅读量:4624 次
发布时间:2019-06-09

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

目录

Java中,synchronized关键字有2种用法:

  1. 作为关键字修饰方法
  2. 修饰一个代码块

线程争用

为了探究synchronized的具体用法,可以用一个简单的程序来说明:

package fc.learn.java.synchronize;import java.util.Random;public class LearningSynchronized {    public enum SyncTypeTag {        OBJ_METHOD, CLASS_METHOD, KEYWARD_METHOD, NORMAL_METHOD    }    static class MyRunnable implements Runnable{        private void counting(){            for (int i = 0; i< 5; i++){                System.out.println(String.format("Thread[%s] count for [%s]", Thread.currentThread().getName(), i));                int sleepSeconds = new Random().nextInt();                sleepSeconds = sleepSeconds % 10;                sleepSeconds = sleepSeconds * sleepSeconds;                sleepSeconds = sleepSeconds % 5;                System.out.println(String.format("Thread[%s] sleep for 0.%s seconds", Thread.currentThread().getName(), sleepSeconds));                try {                    Thread.sleep(sleepSeconds * 100);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }        private void synchronizeObjectMethod() {            synchronized (this){                counting();            }        }        private void synchronizeClasstMethod(){            synchronized (MyRunnable.class){                counting();            }        }        private synchronized void synchronizedMethod(){            counting();        }        private void normalMethod(){            counting();        }        private SyncTypeTag synType;        public MyRunnable(SyncTypeTag type){            this.synType = type;        }        @Override        public void run() {            if (this.synType == SyncTypeTag.OBJ_METHOD) {                synchronizeObjectMethod();            } else if (this.synType == SyncTypeTag.CLASS_METHOD) {                synchronizeClasstMethod();            } else if (this.synType == SyncTypeTag.KEYWARD_METHOD) {                synchronizedMethod();            } else if (this.synType == SyncTypeTag.NORMAL_METHOD) {                normalMethod();            }        }    }    public static void main(String[] args) {        Runnable r1 = new MyRunnable(SyncTypeTag.NORMAL_METHOD);        Runnable r2 = new MyRunnable(SyncTypeTag.NORMAL_METHOD);        Thread t1 = new Thread(r1);        Thread t2 = new Thread(r2);        t1.start();        t2.start();    }}

运行代码,可以获得结果如下:

Thread[Thread-1] count for [0]Thread[Thread-0] count for [0]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [1]Thread[Thread-0] sleep for 0.4 secondsThread[Thread-1] count for [1]Thread[Thread-1] sleep for 0.0 secondsThread[Thread-1] count for [2]Thread[Thread-1] sleep for 0.1 secondsThread[Thread-1] count for [3]Thread[Thread-0] count for [2]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [3]Thread[Thread-0] sleep for 0.4 secondsThread[Thread-1] count for [4]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-0] count for [4]Thread[Thread-0] sleep for 0.1 seconds

也就是说,普通情况下,counting()方法会被线程争用

类锁 synchronized(class)

那么我们加锁试试呢?首先试试对class加锁:

// 之前代码太多不再赘述,此处只展示main方法public static void main(String[] args) {    Runnable r1 = new MyRunnable(SyncTypeTag.CLASS_METHOD);    Runnable r2 = new MyRunnable(SyncTypeTag.CLASS_METHOD);    Thread t1 = new Thread(r1);    Thread t2 = new Thread(r2);    t1.start();    t2.start();}

可以得到如下结果:

Thread[Thread-0] count for [0]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [1]Thread[Thread-0] sleep for 0.0 secondsThread[Thread-0] count for [2]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [3]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [4]Thread[Thread-0] sleep for 0.4 secondsThread[Thread-1] count for [0]Thread[Thread-1] sleep for 0.0 secondsThread[Thread-1] count for [1]Thread[Thread-1] sleep for 0.0 secondsThread[Thread-1] count for [2]Thread[Thread-1] sleep for 0.1 secondsThread[Thread-1] count for [3]Thread[Thread-1] sleep for 0.1 secondsThread[Thread-1] count for [4]Thread[Thread-1] sleep for 0.1 seconds

此时,线程不再争用,目的达到。

对象锁 synchronized(object)

那么试试对象锁:

// 仔细观察,这里用的 this 也就是说,每个线程用的不是同一把锁private void synchronizeObjectMethod() {    synchronized (this){        counting();    }}public static void main(String[] args) {    Runnable r1 = new MyRunnable(SyncTypeTag.CLASS_METHOD);    Runnable r2 = new MyRunnable(SyncTypeTag.CLASS_METHOD);    Thread t1 = new Thread(r1);    Thread t2 = new Thread(r2);    t1.start();    t2.start();}

运行代码:

Thread[Thread-1] count for [0]Thread[Thread-0] count for [0]Thread[Thread-1] sleep for 0.0 secondsThread[Thread-0] sleep for 0.4 secondsThread[Thread-1] count for [1]Thread[Thread-1] sleep for 0.1 secondsThread[Thread-1] count for [2]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-0] count for [1]Thread[Thread-0] sleep for 0.4 secondsThread[Thread-1] count for [3]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-0] count for [2]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [3]Thread[Thread-0] sleep for 0.0 secondsThread[Thread-0] count for [4]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-1] count for [4]Thread[Thread-1] sleep for 0.0 seconds

可以发现,锁并不起作用。这个原因也很容易理解,因为synchronizeObjectMethod方法中用的synchronized(this)进行加锁,而我们有2个进程对象在对counting()方法进行操作,所以会发生争用。如果代码修改为这样:

// synchronizedObjectMethod修改成这样:private void synchronizeObjectMethod(Object globalLock) {    synchronized (globalLock){        counting();    }}// 构造方法和成员变量:private SyncTypeTag synType;private Object globalLock;public MyRunnable(SyncTypeTag type, Object lock){    this.synType = type;    this.globalLock = lock;}@Overridepublic void run() {    if (this.synType == SyncTypeTag.OBJ_METHOD) {        synchronizeObjectMethod(this.globalLock);    } else if (this.synType == SyncTypeTag.CLASS_METHOD) {        synchronizeClasstMethod();    } else if (this.synType == SyncTypeTag.KEYWARD_METHOD) {        synchronizedMethod();    } else if (this.synType == SyncTypeTag.NORMAL_METHOD) {        normalMethod();    }}// main 方法:public static void main(String[] args) {    Object globalLock = new Object();    Runnable r1 = new MyRunnable(SyncTypeTag.OBJ_METHOD, globalLock);    Runnable r2 = new MyRunnable(SyncTypeTag.OBJ_METHOD, globalLock);    Thread t1 = new Thread(r1);    Thread t2 = new Thread(r2);    t1.start();    t2.start();}

运行代码:

Thread[Thread-0] count for [0]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [1]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [2]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [3]Thread[Thread-0] sleep for 0.0 secondsThread[Thread-0] count for [4]Thread[Thread-0] sleep for 0.0 secondsThread[Thread-1] count for [0]Thread[Thread-1] sleep for 0.0 secondsThread[Thread-1] count for [1]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-1] count for [2]Thread[Thread-1] sleep for 0.1 secondsThread[Thread-1] count for [3]Thread[Thread-1] sleep for 0.1 secondsThread[Thread-1] count for [4]Thread[Thread-1] sleep for 0.4 seconds

争用消失。

关键字 synchronized method()

接下来再试试synchronized关键字直接修饰方法:

public static void main(String[] args) {    Object globalLock = new Object();    Runnable r1 = new MyRunnable(SyncTypeTag.KEYWARD_METHOD, globalLock);    Runnable r2 = new MyRunnable(SyncTypeTag.KEYWARD_METHOD, globalLock);    Thread t1 = new Thread(r1);    Thread t2 = new Thread(r2);    t1.start();    t2.start();}

运行代码:

Thread[Thread-0] count for [0]Thread[Thread-1] count for [0]Thread[Thread-0] sleep for 0.0 secondsThread[Thread-1] sleep for 0.1 secondsThread[Thread-0] count for [1]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-1] count for [1]Thread[Thread-0] count for [2]Thread[Thread-1] sleep for 0.1 secondsThread[Thread-0] sleep for 0.1 secondsThread[Thread-0] count for [3]Thread[Thread-0] sleep for 0.1 secondsThread[Thread-1] count for [2]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-0] count for [4]Thread[Thread-0] sleep for 0.4 secondsThread[Thread-1] count for [3]Thread[Thread-1] sleep for 0.4 secondsThread[Thread-1] count for [4]Thread[Thread-1] sleep for 0.1 seconds

依旧会起争用,说明synchronized修饰方法,等于 synchronized(this)

References:

转载于:https://www.cnblogs.com/tflowingcloud/p/8428743.html

你可能感兴趣的文章
Django模板语言
查看>>
Django路由系统
查看>>
提高生产性工具(四) - XML数据库的尝试
查看>>
ural 1005 Stone Pile DP
查看>>
day15—jQuery UI之widgets插件
查看>>
使用ssh和putty操控远程的linux server
查看>>
BZOJ1499: [NOI2005]瑰丽华尔兹
查看>>
过滤器
查看>>
Redis是什么?
查看>>
JavaScript 学习总结
查看>>
iOS开发——UI进阶篇(十)导航控制器、微博详情页、控制器的View的生命周期...
查看>>
多线程(四)线程生命周期和线程池
查看>>
fetch的用法
查看>>
2017.08.11【NOIP提高组】模拟赛B组 小X的佛光
查看>>
【转】[精华] 跟我一起写 Makefile
查看>>
排序俩种方法
查看>>
MVC 三级联动
查看>>
JPA 已作废的SQLQuery.class、setResultTransformer方法替换
查看>>
20190402——第一场UPC团队训练
查看>>
爱奇艺视频广告拦截失败,发文共商大计
查看>>