当前位置:网站首页>Thread safety analysis of [concurrent programming JUC] variables
Thread safety analysis of [concurrent programming JUC] variables
2022-07-01 08:15:00 【Looking at the stars】
List of articles
Whether member variables and static variables are thread safe ?
- If they don't share , Then thread safety
- If they're shared , Depending on whether their state can be changed , There are two more cases
- If there are only read operations , Then thread safety
- If there are read and write operations , Then this code is a critical area , Thread safety needs to be considered
Local variables are thread safe ?
- Local variables are thread safe
- But the objects referenced by local variables may not be
- If the object does not escape the function of the method, access , It's thread safe
- If the object escapes the scope of the method , Thread safety needs to be considered
1 Local variable analysis
Test code :
@Slf4j(topic = "test4")
public class test4 {
public static void test() {
int i = 10;
i++;
}
}
Bytecode ( Compile the code first , Decompiling again :javap -v test4.class)
public static void test();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=0
0: bipush 10
2: istore_0
3: iinc 0, 1
6: return
LineNumberTable:
line 18: 0
line 19: 3
line 20: 6
LocalVariableTable:
Start Length Slot Name Signature
3 4 0 i I
Call per thread test() When the method is used , local variable i Multiple copies will be created in the stack frame memory of each thread , So there is no sharing .
2 Comparative analysis of member variables and local variables
ThreadUnsafe Class has member variables list And three ways ,method2 The way is to list Add elements to it ,method3 It's from list Remove elements from .
When two threads work together on the same list Object time , The following will happen : Threads 1 The added element is not written into memory by the thread 2 interrupt , Threads 2 Add elements and write them into memory , After that thread 1 Then write it into memory , Two additions are equivalent to only one addition , Then remove it twice , There will be errors .
public class TestThreadSafe {
static final int THREAD_NUMBER = 2;
static final int LOOP_NUMBER = 200;
public static void main(String[] args) {
ThreadUnsafe test = new ThreadUnsafe();
for (int i = 0; i < THREAD_NUMBER; i++) {
new Thread(() -> {
test.method1(LOOP_NUMBER);
}, "Thread" + (i+1)).start();
}
}
}
class ThreadUnsafe {
ArrayList<String> list = new ArrayList<>();
public void method1(int loopNumber) {
for (int i = 0; i < loopNumber; i++) {
method2();
method3();
}
}
private void method2() {
list.add("1"); }
private void method3() {
list.remove(0); }
}
Report errors IndexOutOfBoundsException:
Exception in thread "Thread1" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:659)
at java.util.ArrayList.remove(ArrayList.java:498)
at Chapter4.ThreadUnsafe.method3(TestThreadSafe.java:39)
at Chapter4.ThreadUnsafe.method1(TestThreadSafe.java:34)
at Chapter4.TestThreadSafe.lambda$main$0(TestThreadSafe.java:23)
at java.lang.Thread.run(Thread.java:748)
analysis :
- No matter which thread method2 All references are in the same object list Member variables
- method3 And method2 The analysis is the same

When put list Change the member variable to local variable :
public class TestThreadSafe {
static final int THREAD_NUMBER = 2;
static final int LOOP_NUMBER = 200;
public static void main(String[] args) {
ThreadSafe test = new ThreadSafe();
for (int i = 0; i < THREAD_NUMBER; i++) {
new Thread(() -> {
test.method1(LOOP_NUMBER);
}, "Thread" + (i+1)).start();
}
}
}
class ThreadSafe{
public void method1(int loopNumber) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < loopNumber; i++) {
method2(list);
method3(list);
}
}
private void method2(ArrayList<String> list) {
list.add("1"); }
private void method3(ArrayList<String> list) {
list.remove(0); }
}
analysis :
- list It's a local variable , Each thread creates a different instance when it calls , No sharing
- and method2 The parameters are from method1 It's from , And method1 Reference the same object in
- method3 Parameter analysis and method2 identical
- method2 and method3 It's all private methods , operation list There are only these two methods .

3 Local variable exposure reference
Thinking about method access modifiers , If you put method2 and method3 The method of is modified to public Will there be proxy thread safety issues ?
- situation 1: There are other threads calling method2 and method3
- situation 2: In the case 1 On the basis of , by ThreadSafe Class to add subclasses , Subclass coverage method2 or method3 Method , namely
class ThreadSafe{
public void method1(int loopNumber) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < loopNumber; i++) {
method2(list);
method3(list);
}
}
public void method2(ArrayList<String> list) {
list.add("1"); }
public void method3(ArrayList<String> list) {
list.remove(0); }
}
take method2 and method3 The permission modifier of is changed to public, Still thread safe at this point . because , Calling method2 and method3 yes , Operation of the list It's not in method1 Internal list.
Add subclasses ThreadSafeSubClass Inherit ThreadSafe, And rewrite method3 Method , Create a thread inside it to operate list.
class ThreadSafe{
public void method1(int loopNumber) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < loopNumber; i++) {
method2(list);
method3(list);
}
}
public void method2(ArrayList<String> list) {
list.add("1"); }
public void method3(ArrayList<String> list) {
list.remove(0); }
}
class ThreadSafeSubClass extends ThreadSafe{
@Override
public void method3(ArrayList<String> list) {
new Thread(() -> {
list.remove(0);
}).start();
}
}
At this point, there will be a thread safety problem , because method1 establish list The object operation list, call method3 Another thread will be created to operate this list, Multiple threads share list, There will be thread safety issues .
As can be seen from the example private and final Provide 【 Security 】 The significance of .
private Methods that modify cannot be overridden .
final Prevent subclasses from overriding methods .
4 Common thread safety classes
- String
- Integer
- StringBuffer
- Random
- Vector
- Hashtable
- java.util.concurrent Class under package
By saying that they are thread safe, I mean , When multiple threads call a method of their same instance , It's thread safe . It can also be understood as
- Each of their methods is atomic
- But note that the combination of their multiple methods is not atomic , See the analysis later
5 Combination of thread safe class methods
Analyze whether the following code is thread safe ?
Hashtable table = new Hashtable();
// Threads 1, Threads 2
if (table.get("key") == null) {
table.put("key", "value");
}
The possible execution order is as follows :

Ideally , There may only be one thread put; But it's also possible that a thread put End , By another thread put Cover . Cover the previous situation , Missing updates .
Every method in a thread safe class can guarantee atomicity , But composition does not guarantee atomicity . If you want the combination to ensure atomicity , You need to add a protection on the outside of the combination .
6 Immutable thread safety
String、Integer And so on are immutable classes , Because of its internal state ( attribute ) Can't change ( Only read , Can't change ), Therefore, their methods are thread safe
but ,String Yes replace, substring And other methods can change the value , So how do these methods ensure thread safety ?
see String Source code , Among them substring Method creates a new string , It is not a modification of the original string .
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
7 The example analysis
example 1:
Servlet Running on the Tomcat In the environment , There is only one example , Will be tomcat Shared by multiple threads , Therefore, there will be sharing problems among the member variables .
- Map map: Not thread safe , Non thread safe class ,HashTable It's thread safe .
- String S1: Thread safety , Because it is an immutable class .
- final String S2: Same thread safety .
- Date D1: Not thread safe , Non thread safe class .
- final Date D2:Date The object of D2 The reference value of cannot be changed , But the attribute in the date ( Specific date ) You can change , Not thread safe . An immutable reference to an object does not mean that the state of the object is immutable .
example 2:

From the bottom up :
- DAO No member variables , Even if multiple threads access , There is no state to modify , So it's thread safe .
- Connection Is a local variable in a method , Even if there are multiple threads , Other threads cannot access ( Each thread creates a separate Connection), It's also thread safe .
- Service It contains private member variables , But there is nothing else to change it , It is immutable , So it's thread safe .
example 3:
here Connection by DAO Local variables of ,Servelet Only one copy. , therefore Service Only one copy. , therefore DAO Only one copy. , therefore DAO It must be shared by multiple threads , So the variables will be shared by multiple threads . therefore , Not thread safe .
such as , Threads 1 You just created Connection, It's not working yet , Threads 2 Just take Connection Use , After using close, Then there is something wrong with the opportunity .
example 4:
And example 4 comparison ,Dao identical , but Service Different . On each call Service when , Will recreate a new Dao, No will Dao As a Service Member variables of .
Dao by Service Local variables of inner methods , Each new thread creates a new Dao, new Dao It will create a new one Connection, So there will be no thread safety issues . But this way is not very good .
example 5:
although SimpleDateFormat Is the script variable , But it can be achieved through abstract methods foo Exposed to the outside . Its subclasses may have done some improper methods .
among foo I'm not sure about your behavior , May lead to unsafe occurrence , It's called Extraterrestrial method .
Methods or properties that do not want to be exposed are set to final.String That's what the implementation of .
8 exercises
Selling tickets
@Slf4j(topic = "ExerciseSell")
public class ExerciseSell {
public static void main(String[] args) throws InterruptedException {
// Simulate multiple people buying tickets
TicketWindow window = new TicketWindow(1000);
// Statistics of the number of tickets sold
List<Integer> amountList = new Vector<>();
// A combination of all threads
List<Thread> threadList = new ArrayList<>();
// Selling tickets
for (int i = 0; i < 100; i++) {
Thread thread = new Thread(() -> {
// Buy tickets
int amount = window.sell(randomAmount());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
amountList.add(amount);
});
threadList.add(thread);
thread.start();
}
// Wait for the thread to finish running
for (Thread thread : threadList) {
thread.join();
}
// Count the number of votes sold and the number of remaining votes
log.debug(" Surplus ticket :{}", window.getCount());
log.debug(" Number of tickets sold :{}", amountList.stream().mapToInt(i->i).sum());
}
// Random Thread safe
static Random random = new Random();
// Random 1-5
public static int randomAmount() {
return random.nextInt(5) + 1;
}
}
/** * Ticket window */
class TicketWindow {
private int count;
public TicketWindow(int count) {
this.count = count;
}
public int getCount() {
return count;
}
public int sell(int amount) {
if (count >= amount) {
count -= amount;
return amount;
} else {
return 0;
}
}
}
Running more than once may cause errors : The number of votes sold + The number of votes left != Initial votes
Find the critical zone , A critical region : Multithreaded read and write operations on shared resources
Selling tickets window Inside count It's a shared variable
int amount = window.sell(randomAmount());
This is also a shared variable , But it's thread safe .
amountList.add(amount);
So as long as the shared variables involved in the ticket selling action are thread safe , add to synchronized
public synchronized int sell(int amount) {
if (count >= amount) {
count -= amount;
return amount;
} else {
return 0;
}
}
边栏推荐
- 使用beef劫持用戶瀏覽器
- 谈谈数字化转型的几个关键问题
- ContentType所有类型对比
- [website architecture] solve 90% of distributed transactions in one move, and introduce the working principles and application scenarios of database transactions and distributed transactions
- 使用beef劫持用户浏览器
- Tupu software has passed CMMI5 certification| High authority and high-level certification in the international software field
- web254
- 程序员养生宝典
- Anddroid 文本合成语音TTS实现
- 源代码加密的意义和措施
猜你喜欢
![[untitled]](/img/be/3523d0c14d555b293673af2b6fbcff.jpg)
[untitled]

【入门】提取不重复的整数
![[dynamic planning] p1020 missile interception (variant of the longest increasing subsequence)](/img/3e/75a1152f9cdf63c6779fdadec702a0.jpg)
[dynamic planning] p1020 missile interception (variant of the longest increasing subsequence)

Access报表实现小计功能

How to check ad user information?

源代码加密的意义和措施

SharePoint - how to quickly check whether SharePoint is standard or enterprise edition?
![[batch dos-cmd command - summary and summary] - Common operators in the CMD window (<, < <, & <,>, > >, & >, & >, & &, ||, (),;, @)](/img/48/de19e8cc007b93a027a906d4d423b2.png)
[batch dos-cmd command - summary and summary] - Common operators in the CMD window (<, < <, & <,>, > >, & >, & >, & &, ||, (),;, @)

网关gateway-88
![[staff] high and low octave mark (the notes in the high octave mark | mark range are increased by one octave as a whole | low octave mark | mark range are decreased by one octave as a whole)](/img/ff/ebd936eaa6e57b1eabb691b0642957.jpg)
[staff] high and low octave mark (the notes in the high octave mark | mark range are increased by one octave as a whole | low octave mark | mark range are decreased by one octave as a whole)
随机推荐
SharePoint - modify web application authentication using PowerShell
[untitled]
Php laraver Wechat payment
LM08丨网格系列之网格反转(精)
Rumtime 1200 upgrade: London upgrade support, pledge function update and more
Precautions and skills in using regular expressions in golang
seaborn clustermap矩阵添加颜色块
String coordinates of number to excel
7-26 word length (input and output in the loop)
web254
[untitled]
SharePoint - how to quickly check whether SharePoint is standard or enterprise edition?
[redis] it takes you through redis installation and connection at one go
Aardio - 阴影渐变文字
Leetcode T39: 组合总和
[force deduction 10 days SQL introduction] Day9 control flow
P4 安装bmv2 详细教程
Airsim radar camera fusion to generate color point cloud
栈实现计算器
图扑软件通过 CMMI5 级认证!| 国际软件领域高权威高等级认证