成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Synchronized 的幾種錯誤用法,你會了嗎?

開發 前端
在本文中,我們將討論與同步相關的一些不好的做法,以及針對每個使用情況的更好的方法。

大家好, 我是指北君。

synchronized 在我們平常工作中也是挺常用的, 對于擺脫多線程問題很有幫助。但是如果synchronized被錯誤使用時,可能會給我們帶來很多麻煩。

在本文中,我們將討論與同步相關的一些不好的做法,以及針對每個使用情況的更好的方法。

同步的原則

一般來說,我們應該只對那些我們確信沒有外部代碼會鎖定的對象進行同步。

換句話說,使用池化或可重復使用的對象進行同步是一種不好的做法。原因是池化/可重用對象可以被JVM中的其他進程訪問,外部/不被信任的代碼對這些對象的任何修改都會導致死鎖和非確定性行為。

現在,讓我們來討論基于某些類型的同步原則,如String、Boolean、Integer和Object。

String 字面量

1.錯誤用法

字符串字面量是有池的,在Java中經常被重復使用。因此,不建議使用String類型與 synchronized關鍵字進行同步。

public void stringBadPractice1() {
String stringLock = "LOCK_STRING";
synchronized (stringLock) {
// ...
}
}

同樣地,如果我們使用private final String字面,它仍然是從常量池中引用的。

private final String stringLock = "LOCK_STRING";
public void stringBadPractice2() {
synchronized (stringLock) {
// ...
}
}

此外,為了同步,內接字符串被認為是不好的做法。

private final String internedStringLock = new String("LOCK_STRING").intern();
public void stringBadPractice3() {
synchronized (internedStringLock) {
// ...
}
}

根據Javadocs,intern方法為我們獲得了String對象的規范表示。換句話說,intern方法從池中返回一個String--如果它不在池中,則明確地將它添加到池中--它的內容與這個String相同。

因此,在可重用對象上的同步問題對于內部的String對象也是存在的。

注意:所有的String字面符號和以字符串為值的常量表達式都是自動實現的。

2.正確用法

為了避免在String字面上進行同步的不良做法,建議使用new關鍵字創建一個新的String實例。

讓我們在已經討論過的代碼中解決這個問題。首先,我們將創建一個新的String對象,以擁有一個唯一的引用(避免任何重復使用)和它自己的內在鎖,這有助于同步。

然后,我們保持該對象的private和final,以防止任何外部/不受信任的代碼訪問它。

private final String stringLock = new String("LOCK_STRING");
public void stringSolution() {
synchronized (stringLock) {
// ...
}
}

Boolean 字面量

Boolean類型有兩個值,即true和false,不適合用于鎖定目的。與JVM中的String字面量類似,boolean字面量也共享Boolean類的唯一實例。

讓我們來看看一個在Boolean鎖對象上同步的錯誤用法例子。

private final Boolean booleanLock = Boolean.FALSE;
public void booleanBadPractice() {
synchronized (booleanLock) {
// ...
}
}

在這里,如果任何外部代碼也在具有相同值的Boolean字面上進行同步,系統就會變得沒有反應,或者導致死鎖的情況。

因此,我們不建議使用Boolean對象作為同步鎖。

原始類型的包裝類

1. 錯誤用法

與boolean字段類似,原始類型的包裝類可能會重復使用某些值的實例。原因是JVM會緩存和共享可以表示為字節的值。

例如,讓我們寫一個在 Integer 上進行同步的錯誤用法例子。

private int count = 0;
private final Integer intLock = count;
public void boxedPrimitiveBadPractice() {
synchronized (intLock) {
count++;
// ...
}
}

2.正確用法

然而,與boolean字面量不同,在原始類型的包裝類上同步的解決方案是創建一個新實例。

與String對象類似,我們應該使用new關鍵字來創建一個唯一的Integer對象的實例,該實例有自己的內在鎖,并保持其private和final。

private int count = 0;
private final Integer intLock = new Integer(count);
public void boxedPrimitiveSolution() {
synchronized (intLock) {
count++;
// ...
}
}

類同步

當一個類用this關鍵字實現方法同步或塊同步時,JVM使用對象本身作為監視器(其固有鎖)。

不受信任的代碼可以獲得并無限期地持有一個可訪問類的內在鎖。因此,這可能會導致死鎖的情況。

1.錯誤用法

例如,讓我們創建Animal類,它有一個synchronized方法setName和一個帶有synchronized塊的方法setOwner。

public class Animal {
private String name;
private String owner;

// getters and constructors

public synchronized void setName(String name) {
this.name = name;
}

public void setOwner(String owner) {
synchronized (this) {
this.owner = owner;
}
}
}

現在,讓我們寫一些錯誤用法,創建一個Animal類的實例,并對其進行同步。

Animal animalObj = new Animal("Tommy", "John");
synchronized (animalObj) {
while(true) {
Thread.sleep(Integer.MAX_VALUE);
}
}

在這里,不受信任的代碼例子引入了一個無限期的延遲,阻止了setName和setOwner方法的實現獲得同一個鎖。

2.正確用法

防止這個漏洞的解決方案是私人鎖對象。

我們的想法是使用與我們類中定義的Object類的private final實例相關的內在鎖來代替對象本身的內在鎖。

另外,我們應該使用塊同步來代替方法同步,以增加靈活性,使非同步的代碼不在塊中。

所以,讓我們對我們的Animal類進行必要的修改。

public class Animal {
// ...

private final Object objLock1 = new Object();
private final Object objLock2 = new Object();

public void setName(String name) {
synchronized (objLock1) {
this.name = name;
}
}

public void setOwner(String owner) {
synchronized (objLock2) {
this.owner = owner;
}
}
}

在這里,為了提高并發性,我們通過定義多個private final鎖對象來細化鎖定方案,以分離我們對兩個方法--setName和setOwner的同步關注。

此外,如果實現同步塊的方法修改了一個靜態變量,我們必須通過鎖定靜態對象來實現同步。

private static int staticCount = 0;
private static final Object staticObjLock = new Object();
public void staticVariableSolution() {
synchronized (staticObjLock) {
count++;
// ...
}
}

總結

在這篇文章中,我們討論了一些與某些類型的同步有關的壞做法,如String、Boolean、Integer和Object。

本文最重要的啟示是,不建議使用池化或可重復使用的對象進行同步。

另外,建議在Object類的private final實例上進行同步。這樣的對象將無法被外部/不被信任的代碼訪問,否則這些代碼可能會與我們的公共類交互,從而減少這種交互導致死鎖的可能性。

責任編輯:武曉燕 來源: Java技術指北
相關推薦

2022-12-06 08:37:43

2022-07-13 08:16:49

RocketMQRPC日志

2023-09-06 11:31:24

MERGE用法SQL

2023-08-08 08:23:08

Spring日志?線程池

2022-04-13 09:01:45

SASSCSS處理器

2022-03-03 07:34:31

注解容器作用域

2023-07-03 07:20:50

2022-08-09 08:25:44

Stream創建流流計算

2019-05-31 15:10:33

SQL數據庫MySQL

2022-07-08 09:27:48

CSSIFC模型

2019-09-24 21:00:59

SQL數據庫基礎數據庫

2023-12-24 22:30:05

LambdaJava函數

2024-01-19 08:25:38

死鎖Java通信

2022-04-01 08:23:17

InputstreString字符串

2024-02-04 00:00:00

Effect數據組件

2023-07-26 13:11:21

ChatGPT平臺工具

2023-01-10 08:43:15

定義DDD架構

2022-04-11 07:40:45

synchroniz靜態方法程序

2024-02-02 11:03:11

React數據Ref

2025-05-12 00:03:15

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产第一页在线播放 | 日韩一级一区 | 欧美a在线观看 | aaaaaaa片毛片免费观看 | 91视频导航| 日韩欧美1区2区 | 久久久久久久国产 | 久久久国产一区二区三区 | 亚洲精品国产精品国自产在线 | 99久久免费精品国产免费高清 | 亚洲欧美日本在线 | 日韩激情在线 | 九九久久久 | 日韩欧美国产一区二区三区 | 国产精品久久久久久久久久久久午夜片 | 色综合久久久 | www.日韩 | 久久精品成人一区 | 亚洲视频免费一区 | 羞羞网站在线观看 | 天天躁日日躁狠狠的躁天龙影院 | 欧美中文一区 | 亚洲视频在线免费观看 | 国产欧美日韩在线观看 | 成人免费视频观看视频 | 在线观看国产视频 | 久久久久国产精品一区三寸 | 午夜成人免费视频 | 久久久久久国产精品 | 女同av亚洲女人天堂 | 国产精品久久久久一区二区三区 | 一区二区三区久久 | 一级欧美 | 亚洲午夜精品视频 | 中文字幕在线观看一区 | 最新国产精品视频 | 99视频免费在线观看 | 日批免费看 | 国产乱人伦 | 亚洲不卡在线观看 | 在线播放亚洲 |