[Java multithreading] synchronized synchronization method

Mu Xin 2021-11-25 18:30:51
java multithreading synchronized synchronization method

Catalog

1. Method is thread safe

2. Instance variable non thread safe

3. Multiple objects multiple locks

4. synchronized Method and lock object

5. Dirty reading

6. synchronized Lock reentry

7. Something unusual happened , Lock release

8. Synchronization does not have inheritance


“ Non-thread safety ” In fact, it will occur when multiple threads have concurrent access to instance variables in the same object , The result is “ Dirty reading ”, That is, the data obtained is actually changed .

1. Method is thread safe

“ Non-thread safety ” The problem lies in “ Instance variables ” in , If it's a private variable inside the method , There is no “ Non-thread safety ” problem , The result is “ Thread safety ” Of course. .

2. Instance variable non thread safe

If multiple threads access together 1 Instance variables in objects , It is possible that “ Non-thread safety ” problem . Just add a keyword before the method synchronized that will do .

When two threads access synchronous methods in the same object, it must be thread safe .

3. Multiple objects multiple locks

Let's start with an example :

(1) HasSelfPrivateNum.java

public class HasSelfPrivateNum {
private int num = 0;
synchronized public void addI(String username) {
try {
if (username.equals("a")) {
num = 100;
System.out.println("a set over!");
Thread.sleep(2000);
} else {
num = 200;
System.out.println("b set over!");
}
System.out.println(username + " num=" + num);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

(2) ThreadA.java

public class ThreadA extends Thread {
private HasSelfPrivateNum numRef;
public ThreadA(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("a");
}
}

(3) ThreadB.java

public class ThreadB extends Thread {
private HasSelfPrivateNum numRef;
public ThreadB(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("b");
}
}

(4) The main class Run.java

public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();
ThreadA athread = new ThreadA(numRef1);
athread.start();
ThreadB bthread = new ThreadB(numRef2);
bthread.start();
}
}

The operation results are as follows :

a set over!
b set over!
b num=200
a num=100

The above example is a synchronization method in which two threads access different instances of the same class with the same name , The effect does run asynchronously .

From the running results of the above program , Although in HasSelfPrivateNum.java Used in synchronized keyword , But the order of printing is not synchronous , It's crossed . Why is this the result ?

keyword synchronized All locks obtained are object locks , Instead of treating a piece of code or method as a lock , So in the example above , Which thread executes the band first synchronized Keyword method , Hold the lock of the object to which the method belongs Lock, Other threads can only wait , The premise is that multiple threads access the same object .

but If multiple threads access multiple objects , be JVM Multiple locks will be created .

The synchronized word is synchronized, The asynchronous word is asynchronized.

4. synchronized Method and lock object

above 3 The example in proves The thread locks the object . Call the keyword synchronized The declared method must be queued to run . In addition, we need to keep in mind that “ share ” These two words , Only read and write access to shared resources needs to be synchronized , If it's not shared resources , Then there is no need to synchronize .

What effect will other methods have when called ? How to view Lock What about the effect of locking objects ? Let's use an example to illustrate :

(1)MyObject.java

public class MyObject {
synchronized public void methodA() {
try {
System.out.println("begin methodA threadName="
+ Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("end endTime=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void methodB() {
try {
System.out.println("begin methodB threadName="
+ Thread.currentThread().getName() + " begin time="
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

(2) ThreadA.java

public class ThreadA extends Thread {
private MyObject object;
public ThreadA(MyObject object) {
super();
this.object = object;
}
@Override
public void run() {
super.run();
object.methodA();
}
}

(3) ThreadB.java

public class ThreadB extends Thread {
private MyObject object;
public ThreadB(MyObject object) {
super();
this.object = object;
}
@Override
public void run() {
super.run();
object.methodB();
}
}

(4) Run.java

public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
ThreadA a = new ThreadA(object);
a.setName("A");
ThreadB b = new ThreadB(object);
b.setName("B");
a.start();
b.start();
}
}

Running results :

begin methodA threadName=A
begin methodB threadName=B begin time=1633888880077
end endTime=1633888885092
end

Through the above experiment, we can know , Although threads A Hold on first object The lock of the object , But threads B You can call non asynchronously synchronized Method of type .

Continue the experiment , take MyObject.java In the document methodB() Add... Before the method synchronized keyword , This example is Two synchronous methods for two threads to access the same object . The running result is :

begin methodA threadName=A
end endTime=1633889057071
begin methodB threadName=B begin time=1633889057075
end

The experimental conclusion of this section is :

(1)A Thread first holds object Object's Lock lock ,B Threads can call... Asynchronously object The non in the object synchronized Method of type .

(2)A Thread first holds object Object's Lock lock ,B If the thread calls at this time object Object synchronized Type methods need to wait , That is synchronization .

【 notes 】: It can be understood as ,synchronized Lock object , Locks all of the objects at the same time synchronized Method of type .

5. Dirty reading

Although some programs are synchronized during assignment , However, there may be some unexpected accidents when taking values , This situation is “ Dirty reading ”(dirtyRead).

According to the above 4 The conclusion in this paper can be seen , The way to avoid dirty reading can be in setValue() and getValue() Add... Before the method synchronized keyword .

When A Thread calls MyObject Add... To the object synchronized Keywords X When the method is used ,A The thread gets A Method lock , To be exact , It's the lock of the object , So other threads have to wait A The thread can only be called after the execution of the thread X Method , but B The thread can call other non synchronized Synchronization method .

When A Thread calls MyObject Object to join synchronized When a keyword ,A Object gets X The lock of the object where the method is located , So other threads have to wait A The thread can only be called after the execution of the thread X Method , and B If the thread declares synchronized Key words are not X When the method is used , Must wait A Thread will X The method is finished , Only after the object lock is released can . This is a A The thread has executed a complete task .

Dirty reads must occur when operating instance variables , This is the different threads “ Scramble for ” The result of the instance variable .

6. synchronized Lock reentry

keyword synchronized It has the function of lock re-entry , That is to say, they are using synchronized when , When a thread gets an object lock , When you request this object lock again, you can get the lock of the object again .

【 notes 】: It means , When a thread gets an object lock , You can access all of this object synchronized Methods , Of course, you can also access non synchronized Method .

The concept of reentrant lock is : You can get your own internal lock again . For example, a thread obtains the lock of an object , At this time, the object has not been released , When it wants to get the lock of this object again, it can still get , If it's not lockable for re-entry , It causes a deadlock .

This also proves that in a synchronized Method / Block to call other methods of this class / When a block , You can always get a lock .

Here is an example to illustrate :

(1)Service.java

public class Service {
synchronized public void service1() {
System.out.println("service1");
service2();
}
synchronized public void service2() {
System.out.println("service2");
service3();
}
synchronized public void service3() {
System.out.println("service3");
}
}

(2) MyThread.java

public class MyThread extends Thread {
@Override
public void run() {
Service service = new Service();
service.service1();
}
}

(3) Run.java

public class Run {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}

Running results :

service1
service2
service3

Reentrant locks are also supported in the context of parent-child inheritance .

The following example proves this :

(1)Main.java

public class Main {
public int i = 10;
synchronized public void operateIMainMethod() {
try {
i--;
System.out.println("main print i=" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

(2) Sub.java

public class Sub extends Main {
synchronized public void operateISubMethod() {
try {
while (i > 0) {
i--;
System.out.println(" -- sub print i=" + i);
Thread.sleep(100);
this.operateIMainMethod();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

(3) MyThread.java

public class MyThread extends Thread {
@Override
public void run() {
Sub sub = new Sub();
sub.operateISubMethod();
}
}

(4) Run.java

public class Run {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}

Running results :

 -- sub print i=9
main print i=8
-- sub print i=7
main print i=6
-- sub print i=5
main print i=4
-- sub print i=3
main print i=2
-- sub print i=1
main print i=0

This experiment shows that , When there is a parent-child inheritance relationship , Subclasses can be passed through “ Reentrant lock ” Call the synchronization method of the parent class .

7. Something unusual happened , Lock release

When an exception occurs in the code executed by a thread , The lock it holds will automatically release .

8. Synchronization does not have inheritance

Synchronization cannot be inherited .

The following is an example to verify .

(1) Main.java

public class Main {
synchronized public void serviceMethod() {
try {
System.out.println("main " + Thread.currentThread().getName() + " sleep begin threadName="
+ " time="
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("main " + Thread.currentThread().getName() + " sleep end threadName="
+ " time="
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

(2) Sub.java

public class Sub extends Main {
@Override
public void serviceMethod() {
try {
System.out.println(" -- sub " + Thread.currentThread().getName() + " sleep begin threadName="
+ " time = "
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" -- sub " + Thread.currentThread().getName() + " sleep end threadName="
+ " time="
+ System.currentTimeMillis());
super.serviceMethod();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

(3) MyThreadA.java

public class MyThreadA extends Thread {
private Sub sub;
public MyThreadA(Sub sub) {
super();
this.sub = sub;
}
@Override
public void run() {
sub.serviceMethod();
}
}

(4) MyThreadB.java

public class MyThreadB extends Thread {
private Sub sub;
public MyThreadB(Sub sub) {
super();
this.sub = sub;
}
@Override
public void run() {
sub.serviceMethod();
}
}

(5) Run.java

public class Run {
public static void main(String[] args) {
Sub subRef = new Sub();
MyThreadA a = new MyThreadA(subRef);
a.setName("A");
a.start();
MyThreadB b = new MyThreadB(subRef);
b.setName("B");
b.start();
}
}

Running results :

 -- sub B sleep begin threadName= time = 1633892050675
-- sub A sleep begin threadName= time = 1633892050675
-- sub A sleep end threadName= time=1633892055699
-- sub B sleep end threadName= time=1633892055699
main A sleep begin threadName= time=1633892055699
main A sleep end threadName= time=1633892060700
main B sleep begin threadName= time=1633892060700
main B sleep end threadName= time=1633892065701

As can be seen from this example , Synchronization cannot inherit , So you have to add... To the methods of subclasses synchronized keyword . The operation effect after adding is as follows :

 -- sub A sleep begin threadName= time = 1633892420973
-- sub A sleep end threadName= time=1633892425991
main A sleep begin threadName= time=1633892425991
main A sleep end threadName= time=1633892430991
-- sub B sleep begin threadName= time = 1633892430991
-- sub B sleep end threadName= time=1633892435991
main B sleep begin threadName= time=1633892435991
main B sleep end threadName= time=1633892440992
版权声明
本文为[Mu Xin]所创,转载请带上原文链接,感谢
https://javamana.com/2021/11/20211109101849543m.html

  1. Flink Handling Function Real War II: processfunction class, Java thread interview subject
  2. Oracle SQL injection summary
  3. [Java data structure] you must master the classic example of linked list interview (with super detailed illustration and code)
  4. Record a java reference passing problem
  5. spring JTA 關於异常處理的時機問題
  6. Java - Set - Map (double file) - dija Rewriting, 2021 Java Developer's Performance Optimization
  7. Android入门教程 | OkHttp + Retrofit 取消请求的方法
  8. Java 8 Stream API and common methods, Java Junior Program interview
  9. Github 疯传!史上最强!BAT 大佬,2021年最新Java大厂面试笔试题分享
  10. git(3)Git 分支,zookeeper下载教程
  11. Java Backend Internet 500 questions d'entrevue moyennes et avancées (y compris les réponses), technologie de crochet Linux
  12. Entretien d'entretien d'usine Java post sprint de 100 jours - accumulation de jours et de mois, trois questions par jour [jour 12, fonction de principe de Zookeeper
  13. Tutoriel Java - reflection, tutoriel de téléchargement mongodb
  14. How to analyze several common key and hot issues in redis from multiple dimensions
  15. GIT (3) GIT Branch, Zookeeper Download tutoriel
  16. Tutoriel de démarrage Android | okhttp + Retrofit comment annuler une demande
  17. Design pattern [3.3] - Interpretation of cglib dynamic agent source code
  18. Share the actual operation of private collection project nodejs backend + Vue + Mysql to build a management system
  19. Springboot has 44 application initiators
  20. GitHub上霸榜久居不下的《Java面试突击宝典》,java图形用户界面设计基础
  21. GitHub上访问下载破百万的神仙文档《Java面试神技》看完我呆了,java面试问项目中遇到的问题
  22. GitHub上标星75k 超牛的《Java面试突击版,java高级工程师技能
  23. GitHub上标星2,java项目开发实训教程
  24. Docker development environment Preview
  25. JavaScript高級深入淺出:掌握 this 指向
  26. JavaScript Advanced Insight and outside: Mastering this direction
  27. Vue de l'application pratique de Javascript, drop drag Event
  28. docker 安装部署 Jenkins 2.322
  29. kafka安装
  30. 近九万字图文详解RabbitMQ
  31. Engaged in Java for one and a half years, how to break through yourself
  32. 输出9*9乘法表----java
  33. 判断一个数是不是素数-------java
  34. java项目,记录页面修改值,内部打“官司”用
  35. Docker installation Deployment Jenkins 2.322
  36. Comment porter un pantalon en hiver? Les petits hommes, les jambes épaisses et la largeur de l'entrejambe peuvent être vus. 3 techniques pour éviter la foudre
  37. MySQL下载和安装教程
  38. In depth analysis of rocketmq source code - message storage module
  39. Spring transaction management
  40. mysql恢复ibd数据,为何频频报错?
  41. [skills with annual salary of 60W] after working for 5 years, do you really understand netty and why to use it? (deep dry goods)
  42. Pourquoi MySQL récupère - t - il fréquemment les données ibd?
  43. Tutoriels de téléchargement et d'installation MySQL
  44. In IntelliJ idea, develop a fishing and reading plug-in
  45. Talk about how to integrate SPI with spring
  46. 重学Spring系列之Swagger2.0和Swagger3.0
  47. Hadoop05【命令操作】,Java400道面试题通关宝典助你进大厂
  48. Guava Cache缓存设计原理,java基础入门
  49. Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器
  50. gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版
  51. Projet Java, enregistrer la valeur de modification de la page, utilisé pour les litiges internes
  52. Déterminer si un nombre est un nombre premier - - Java
  53. Sortie 9 * 9 tableau de multiplication - Java
  54. Plusieurs façons de réinitialiser le déplacement du Groupe de consommateurs Kafka
  55. GRPC Learning six: GRPC Gateway Integrated Swagger, Java language programming and data structure Advanced Edition
  56. python数据结构:数组、列表、栈、队列及实现
  57. Gson: json Parser for github Star 18k, Java json Parser from Google
  58. Principes de conception du cache Guava, Introduction à la base Java
  59. Un pantalon beige = élégant, blanc + haut de gamme, si beau cet hiver!
  60. Hadoop05 【 commande 】, Java 400 questions d'entrevue pour vous aider à entrer dans l'usine