当前位置:网站首页>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;
}
}
边栏推荐
- SharePoint - modify web application authentication using PowerShell
- [untitled]
- P4 安装bmv2 详细教程
- getInputStream() has already been called for this request
- 【入门】截取字符串
- Hijacking a user's browser with beef
- Gdip - hatchbrush pattern table
- [staff] key number (key number identification position | key number marking list | a major key identification principle | F, C, G position marking ascending | F major key identification principle | B
- Li Kou daily question - day 31 -1790 Can a string exchange be performed only once to make two strings equal
- 如何使用layui将数据库中的数据以表格的形式展现出来
猜你喜欢

【Redis】一气呵成,带你了解Redis安装与连接

Lm08 mesh series mesh inversion (fine)

web254

Learn reptiles for a month and earn 6000 a month? Tell you the truth about the reptile, netizen: I wish I had known it earlier

Teach you how to apply for domestic trademark online step by step

Access报表实现小计功能

SharePoint - how to quickly check whether SharePoint is standard or enterprise edition?

【无标题】

seaborn clustermap矩阵添加颜色块

Android screen adaptation (using constraintlayout), kotlin array sorting
随机推荐
Li Kou daily question - day 31 -1502 Judge whether an arithmetic sequence can be formed
[getting started] input n integers and output the smallest K of them
[getting started] enter the integer array and sorting ID, and sort its elements in ascending or descending order
OJ input and output exercise
Precautions and skills in using regular expressions in golang
Five combination boxing, solving six difficult problems on campus and escorting the construction of educational informatization
sqlalchemy创建MySQL_Table
How to get a SharePoint online site created using the office365 group template
How to troubleshoot SharePoint online map network drive failure?
Differential: definition of total differential, partial derivative, gradient
【网站架构】一招搞定90%的分布式事务,实打实介绍数据库事务、分布式事务的工作原理应用场景
力扣每日一题-第32天-1822.数组元素积的符号
Li Kou daily question - day 31 -202 Happy number
Codeforces Round #803 (Div. 2) VP补题
Provincial selection + noi Part II string
ContentType所有类型对比
Li Kou daily question - day 31 -1790 Can a string exchange be performed only once to make two strings equal
凸印的印刷原理及工艺介绍
P4 安装bmv2 详细教程
【入门】输入n个整数,输出其中最小的k个