Java synchronized 关键字详解

时间:2023-05-16

Javasynchronized关键字详解
前置技能点
进程和线程的概念
线程创立方式
线程的状态状态转换
线程安全的概念
synchronized关键字的几种用法
润饰非静态成员办法
synchronizedpublicvoidsync(){
}
润饰静态成员办法
synchronizedpublicstaticvoidsync(){
}
类锁代码块
synchronized(类.class){
}
目标锁代码块
synchronized(this|目标){
}
synchronized润饰非静态办法时能够看做是锁this目标,润饰静态办法时能够看做是锁办法地点的类。
synchronized关键字的根本机制
各个线程想要拜访被synchronized润饰的代码块,就要取得synchronized声明的锁。假如两个线程的目标是同一个锁,就会呈现阻塞的现象,所以两个线程不能同时拜访同一个锁下的代码,保证了多线程在履行时终究成果不会犯错。这与同享变量是否为静态无关。2024澳门原料网1688白老虎
几个比如
目标锁
publicclassThreadDemoextendsThread{@Overridepublicsynchronizedvoidrun(){for(inti=0;i<10000;i++){
Main.i++;
}
System.out.println(“履行完结”);
}
}
直接将承继的run()办法标记为synchronized,作用是对Main类中的i变量做10000次累加操作。
publicclassMain{staticinti=0;publicstaticvoidmain(String[]args)throwsInterruptedException{
ThreadDemothreadDemo=newThreadDemo();
Threadt1=newThread(threadDemo);
Threadt2=newThread(threadDemo);
Threadt3=newThread(threadDemo);
Threadt4=newThread(threadDemo);
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(i);
}
}//输出成果://履行完结//履行完结//履行完结//履行完结//40000
能够看到当4个线程悉数履行结束之后,变量i成功的累加了40000次,没有呈现丢失操作的状况。
假如咱们将main()办法修正如下:
publicstaticvoidmain(String[]args)throwsInterruptedException{
Threadt1=newThreadDemo();
Threadt2=newThreadDemo();
Threadt3=newThreadDemo();
Threadt4=newThreadDemo();
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(i);
}//输出成果://履行完结//履行完结//履行完结//履行完结//27579
能够看到丢失了不少的累加操作。调查前后两个main()办法创立线程的方式能够发现,前面的main()办法是使用了同一个目标来创立了4个不同的线程,而后一个main()办法使用了4个不同的ThreadDemo目标创立了4个线程。咱们用synchronized润饰的是一个非静态成员函数,相当于对该办法创立了this的目标锁。在第一个main()办法中使用同一个目标来创立4个不同线程就会让4个线程抢夺同一个目标锁,这样,在同一时间内,仅能有一个线程能拜访synchronized润饰的办法。而在第二种main()办法中,4个线程各自对应一个目标锁,4个线程之间没有竞赛关系,目标锁自然无法收效。
类锁
publicclassThreadDemoextendsThread{@Overridepublicvoidrun(){synchronized(ThreadDemo.class){for(inti=0;i<10000;i++){
Main.i++;
}
System.out.println(“履行完结”);
}
}
}
将润饰办法的synchronized改为对ThreadDemo.class上锁的代码块
publicclassThreadDemo2extendsThread{@Overridepublicvoidrun(){synchronized(ThreadDemo2.class){for(inti=0;i<10000;i++){
Main.i++;
}
System.out.println(“履行完结”);
}
}
}
再创立一个相同的类命名为ThreadDemo2,与ThreadDemo不同的是,ThreadDemo2中,synchronized对ThreadDemo2.class上锁。
publicstaticvoidmain(String[]args)throwsInterruptedException{
Threadt1=newThreadDemo();
Threadt2=newThreadDemo();
Threadt3=newThreadDemo2();
Threadt4=newThreadDemo2();
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(i);
}//输出成果://履行完结//履行完结//履行完结//履行完结//33054
4个线程别离由ThreadDemo和ThreadDemo2来创立,明显得到的成果与预期的40000不符。假如咱们将ThreadDemo2中的synchronized改为对ThreadDemo.class上锁:
publicclassThreadDemo2extendsThread{@Overridepublicvoidrun(){synchronized(ThreadDemo.class){for(inti=0;i<10000;i++){
Main.i++;
}
System.out.println(“履行完结”);
}
}
}//输出成果://履行完结//履行完结//履行完结//履行完结//40000
能够看到,虽然是声明在两个不同的类中的synchronized代码块,可是由于都是对ThreadDemo.class上锁,所以4个线程之间还是建立了竞赛关系,同时只能有一个线程拜访被synchronized润饰的代码。
总结
所以synchronized关键字的本质是约束线程拜访一段代码,而约束的条件就是,在所有被加上相同锁的代码上,同一时间,只能有一个线程在运行。这与你要修正什么样的同享变量无关。在我刚接触到的时候认为类锁和目标锁是别离针对静态同享变量和非静态同享变量的,但事实上锁的是要履行的代码块,而不是代码块即将拜访的同享变量。

文章标签:

Copyright © 2016 2024澳门原料网1688白老虎,保留所有权利。 粤ICP备09033321号

2024澳门原料网1688白老虎 2024澳门原料网1688白老虎
2024澳门原料网1688白老虎
扫描二维码
与项目经理交流
2024澳门原料网1688白老虎 2024澳门原料网1688白老虎
2024澳门原料网1688白老虎
扫描二维码
与项目经理交流
2024澳门原料网1688白老虎
ciya68