第66条:同步访问共享的可变数据《高效java》

同步.jpg

关键字:synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法,或者某一个代码块。

同步

概念:

单线程

理解:

1、当一个对象被一个线程修改的时候,可以组织另一个线程观察到对象内部不一致的状态。
2、如果没有同步,一个线程的变化就不能被其他线程看到。同步不仅可以阻止一个线程看到对象处于不一致的状态,还可以保证进入同步代码块的线程看到同一个锁之前所有的修改效果。

原子性

概念

原子是
读或写一个非long或double的基本类型变量是原子的

理解

如果把一个事务可看作是一个程序,它要么完整的被执行,要么完全不执行。这种特性就叫原子性

应用场景:一个线程干扰另一个线程任务

如果需要停止一个线程,可以使用Thread.stop方法,但是这个方法很久以前就不提倡使用了,因为不安全——使用它会使数据被破坏。
因此,建议的做法是,让一个线程轮询一个boolean域,另一个线程设置这个boolean域即可

错误示例

public class Temp {  
  
    private static boolean stopRequested;  
  
    public static void main(String[] args) throws InterruptedException {  
        Thread backgroundThread = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                int i = 0;  
                while (!stopRequested) {  
                    i++;  
                }  
            }  
        });  
        backgroundThread.start();  
        TimeUnit.SECONDS.sleep(1);  
        stopRequested = true;  
    }  
  
}  

实际上以上这段程序会永远的运行下去,因为没有使用同步,无法保证后台进程可以看到stopRequested值的改变。虚拟机将代码:

while (!stopRequested) {  
    i++;  
}  

编译成:

if(!stopRequested)  
    while(true)  
        {  
            i++;  
        }  

这样一来,永远都不会看到stopRequested的改变。

修正示例-使用synchronized

private static boolean stopRequested;  
  
private static synchronized void requestStop() {  
    stopRequested = true;  
}  
  
private static synchronized boolean stopRequested() {  
    return stopRequested;  
}  
  
public static void main(String[] args) throws InterruptedException {  
    Thread backgroundThread = new Thread(new Runnable() {  
        @Override  
        public void run() {  
            int i = 0;  
            while (!stopRequested()) {  
                i++;  
            }  
        }  
    });  
    backgroundThread.start();  
    TimeUnit.SECONDS.sleep(1);  
    requestStop();  
}  

修正示例-使用volatile

private static volatile boolean stopRequested;  
  
public static void main(String[] args) throws InterruptedException {  
    Thread backgroundThread = new Thread(new Runnable() {  
        @Override  
        public void run() {  
            int i = 0;  
            while (!stopRequested) {  
                i++;  
            }  
        }  
    });  
    backgroundThread.start();  
    TimeUnit.SECONDS.sleep(1);  
    stopRequested = true;  
}  

==注意==:使用volatile容易出现错误

private static volatile int nextSerialNumber = 0;  
  
public static int generateSerialNumber() {  
    return nextSerialNumber++;  
}

尽管使用了volatile,但是由于++运算符不是原子的,因此在多线程的时候会出错。++运算符执行两项操作:1、读取值;2、写回新值(相当于原值+1)。如果第二个线程在第一个线程读取旧值和写会新值的时候读取了这个域,就会产生错误,他们会得到相同的SerialNumber。
解决方法可以是,加入synchronized并去掉volatile。进一步的,可以用Long来代替int,或者在快要溢出的时候,抛出异常。更好的是使用AtomicLong类。

private static final AtomicLong nextSerialNumber = new AtomicLong(0);  
  
public static Long generateSerialNumber() {  
    return nextSerialNumber.incrementAndGet();  
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容