java基础Synchronized关键字之对象锁
java中synchronized关键字之对象锁
当有多个线程对一个共享数据进行操作时,需要注意多线程的安全问题。
多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。而用的最多的就是synchronized关键字。
语法:synchronized(对象锁){}
被synchronized关键字修饰的一个方法,则这个方法叫做同步方法
当synchronized方法执行完或发生异常时,会自动释放锁。
1.是否使用synchronized关键字的不同
package threaddemo; public class threaddemo { public static void main(string[] args) { example example = new example(); thread t1 = new th(example); thread t2 = new th(example); t1.start(); t2.start(); } } class example { public synchronized void show() { for (int i = 0; i < 10; ++i) { try { thread.sleep(500); } catch (interruptedexception e) { e.printstacktrace(); } system.out.println(i); } } } class th extends thread { private example example; public th(example example) { this.example = example; } @override public void run() { example.show(); } }
运行结果:
show()0 show()1 show()2 show()3 show()4 show()5 show()6 show()7 show()8 show()9 show2()0 show2()1 show2()2 show2()3 show2()4 show2()5 show2()6 show2()7 show2()8 show2()9
是否在show()方法前加上synchronized关键字,这个例子程序的执行结果会有很大的不同。
如果不加synchronized关键字,则两个线程同时执行show()方法,输出是两组并发的。
如果加上synchronized关键字,则会先输出一组0到9,然后再输出下一组,说明两个线程是顺次执行的。
2.同步方法的锁是this
在静态同步方法中的对象锁是这个类的字节码文件对象。类.class
要想获取一个类的字节码文件对象,有两种方法
1通过当前类.class
2通过当前类的实例对象.getclass()方法获取
public class classdemo { void show(){ //任何一个类可以通过.class来获取字节码文件对象 class<classdemo> c = classdemo.class; //任何一个对象可以通过getclass()方法来获取字节码文件对象 class<? extends classdemo> class1 = new classdemo().getclass(); } }
验证同步方法的对象锁是this
思路:
启动两个线程,让一个线程进入同步代码块,一个线程进入同步方法
用到了一个中间的控制变量boolean flag
线程对象的run中,实现三个窗口出售100张票的功能,让程序进入一个同步代码块中,并且在线程对象中,再定义一个同步方法,功能与同步代码块中的功能相同。
package threaddemo;
public class threaddemo03 {
public static void main(string[] args) {
t t = new t();
thread t1 = new thread(t);
thread t2 = new thread(t);
t1.start();
try {
thread.sleep(50);
} catch (exception e) {
e.printstacktrace();
}
t.flag=false;
t2.start();
}
}
class t implements runnable {
private int ticket = 100;
boolean flag = true;
object obj = new object();
@override
public void run() {
if (flag) {
while (true) {
//synchronized (this) {
synchronized (obj){
if (ticket > 0) {
try {
thread.sleep(50);
} catch (exception e) {
e.printstacktrace();
}
system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票");
}
}
}
}else{
while(true){
show();
}
}
}
public synchronized void show(){//synchronized (this)
if (ticket > 0) {
try {
thread.sleep(50);
} catch (exception e) {
e.printstacktrace();
}
system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票");
}
}
}
运行结果:
thread-0正在出售第100张票 thread-1正在出售第99张票 thread-0正在出售第98张票 thread-1正在出售第97张票 thread-0正在出售第96张票 thread-1正在出售第95张票 thread-0正在出售第94张票 thread-1正在出售第93张票 thread-0正在出售第92张票 thread-1正在出售第91张票 thread-0正在出售第90张票 thread-1正在出售第89张票 thread-0正在出售第88张票 thread-1正在出售第87张票 thread-0正在出售第86张票 thread-1正在出售第85张票 thread-0正在出售第84张票 thread-1正在出售第83张票 thread-0正在出售第82张票 thread-1正在出售第81张票 thread-0正在出售第80张票 thread-1正在出售第79张票 thread-0正在出售第78张票 thread-1正在出售第77张票 thread-0正在出售第76张票 thread-1正在出售第75张票 thread-0正在出售第74张票 thread-1正在出售第73张票 thread-0正在出售第72张票 thread-1正在出售第71张票 thread-0正在出售第71张票 thread-1正在出售第70张票 thread-0正在出售第69张票 thread-1正在出售第68张票 thread-0正在出售第68张票 thread-1正在出售第66张票 thread-0正在出售第67张票 thread-1正在出售第65张票 thread-0正在出售第65张票 thread-0正在出售第64张票 thread-1正在出售第63张票 thread-0正在出售第62张票 thread-1正在出售第61张票 thread-1正在出售第60张票 thread-0正在出售第59张票 thread-0正在出售第58张票 thread-1正在出售第57张票 thread-1正在出售第56张票 thread-0正在出售第55张票 thread-1正在出售第54张票 thread-0正在出售第54张票 thread-1正在出售第53张票 thread-0正在出售第52张票 thread-1正在出售第51张票 thread-0正在出售第50张票 thread-0正在出售第49张票 thread-1正在出售第48张票 thread-0正在出售第47张票 thread-1正在出售第47张票 thread-1正在出售第46张票 thread-0正在出售第45张票 thread-1正在出售第44张票 thread-0正在出售第43张票 thread-0正在出售第42张票 thread-1正在出售第41张票 thread-0正在出售第40张票 thread-1正在出售第39张票 thread-0正在出售第38张票 thread-1正在出售第37张票 thread-0正在出售第36张票 thread-1正在出售第35张票 thread-0正在出售第34张票 thread-1正在出售第33张票 thread-0正在出售第32张票 thread-1正在出售第31张票 thread-0正在出售第30张票 thread-1正在出售第29张票 thread-0正在出售第28张票 thread-1正在出售第27张票 thread-0正在出售第26张票 thread-1正在出售第25张票 thread-0正在出售第24张票 thread-1正在出售第23张票 thread-0正在出售第22张票 thread-1正在出售第21张票 thread-0正在出售第20张票 thread-1正在出售第19张票 thread-0正在出售第18张票 thread-1正在出售第17张票 thread-0正在出售第16张票 thread-1正在出售第15张票 thread-0正在出售第14张票 thread-1正在出售第13张票 thread-0正在出售第12张票 thread-1正在出售第11张票 thread-0正在出售第10张票 thread-1正在出售第9张票 thread-0正在出售第8张票 thread-1正在出售第7张票 thread-0正在出售第6张票 thread-1正在出售第5张票 thread-0正在出售第4张票 thread-1正在出售第3张票 thread-0正在出售第2张票 thread-1正在出售第1张票 thread-0正在出售第0张票
通过改变class t中同步代码块synchronized (对象锁) 的对象锁obj改成this依然成立。所以同步方法的对象锁是this。
其中public synchronized void show()就相当于synchronized (this)
静态同步方法的对象锁是类的字节码文件对象 类.class | 对象.getclass()
package threaddemo; public class threaddemo2 { /* * 通过验证发现同步函数,如果被静态修饰后,不再以this为锁静态进内存时,内存中没有本类的对象, * 但一定有该类的字节码文件对象 类名.class * 该对象的类型是class 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class */ public static void main(string[] args) { ticket t = new ticket(); thread t1 = new thread(t); thread t2 = new thread(t); // 开启第一个线程 但不一定马上执行 t1.start(); t.flag = false;// 改变标志 try { thread.sleep(50); } catch (exception e) { } // 让主线程睡眠50毫秒 保证第一个线程先开始运行 且标志位改变 t2.start(); } } class ticket implements runnable { private static int ticket = 100; boolean flag = true; public void run() { if (flag) { while (true) { // synchronized(this) synchronized (ticket.class) { if (ticket > 0) { try { thread.sleep(50); } catch (exception e) { } system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票"); } } } } else while (true) show(); } // 静态同步函数 该类对应的字节码文件对象为锁 public static synchronized void show(){//synchronized (this) if (ticket > 0) { try { thread.sleep(50); } catch (exception e) { } system.out.println(thread.currentthread().getname() + "正在出售第" + ticket-- + "张票"); } } }
运行结果:
thread-0正在出售第100张票 thread-0正在出售第99张票 thread-0正在出售第98张票 thread-0正在出售第97张票 thread-0正在出售第96张票 thread-0正在出售第95张票 thread-0正在出售第94张票 thread-0正在出售第93张票 thread-0正在出售第92张票 thread-0正在出售第91张票 thread-1正在出售第90张票 thread-1正在出售第89张票 thread-1正在出售第88张票 thread-0正在出售第87张票 thread-1正在出售第86张票 thread-1正在出售第85张票 thread-0正在出售第84张票 thread-0正在出售第83张票 thread-1正在出售第82张票 thread-1正在出售第81张票 thread-0正在出售第80张票 thread-0正在出售第79张票 thread-1正在出售第78张票 thread-0正在出售第77张票 thread-1正在出售第76张票 thread-1正在出售第75张票 thread-1正在出售第74张票 thread-0正在出售第73张票 thread-0正在出售第72张票 thread-1正在出售第71张票 thread-1正在出售第70张票 thread-1正在出售第69张票 thread-0正在出售第68张票 thread-1正在出售第67张票 thread-0正在出售第66张票 thread-0正在出售第65张票 thread-0正在出售第64张票 thread-0正在出售第63张票 thread-0正在出售第62张票 thread-1正在出售第61张票 thread-1正在出售第60张票 thread-1正在出售第59张票 thread-0正在出售第58张票 thread-0正在出售第57张票 thread-0正在出售第56张票 thread-0正在出售第55张票 thread-0正在出售第54张票 thread-0正在出售第53张票 thread-0正在出售第52张票 thread-0正在出售第51张票 thread-1正在出售第50张票 thread-1正在出售第49张票 thread-0正在出售第48张票 thread-0正在出售第47张票 thread-0正在出售第46张票 thread-0正在出售第45张票 thread-0正在出售第44张票 thread-1正在出售第43张票 thread-1正在出售第42张票 thread-0正在出售第41张票 thread-1正在出售第40张票 thread-0正在出售第39张票 thread-0正在出售第38张票 thread-0正在出售第37张票 thread-0正在出售第36张票 thread-0正在出售第35张票 thread-0正在出售第34张票 thread-0正在出售第33张票 thread-0正在出售第32张票 thread-1正在出售第31张票 thread-1正在出售第30张票 thread-1正在出售第29张票 thread-1正在出售第28张票 thread-1正在出售第27张票 thread-1正在出售第26张票 thread-1正在出售第25张票 thread-1正在出售第24张票 thread-0正在出售第23张票 thread-0正在出售第22张票 thread-0正在出售第21张票 thread-1正在出售第20张票 thread-0正在出售第19张票 thread-0正在出售第18张票 thread-0正在出售第17张票 thread-1正在出售第16张票 thread-1正在出售第15张票 thread-1正在出售第14张票 thread-1正在出售第13张票 thread-0正在出售第12张票 thread-1正在出售第11张票 thread-0正在出售第10张票 thread-0正在出售第9张票 thread-0正在出售第8张票 thread-1正在出售第7张票 thread-0正在出售第6张票 thread-0正在出售第5张票 thread-0正在出售第4张票 thread-1正在出售第3张票 thread-1正在出售第2张票 thread-0正在出售第1张票
推荐阅读
-
java并发笔记四之synchronized 锁的膨胀过程(锁的升级过程)深入剖析
-
Java基础知识之this关键字知识讲解
-
java基础Synchronized关键字之对象锁
-
【java基础】面试常见问题:类和对象,封装继承多态,final关键字,static关键字,类加载过程,双亲委派模型
-
Java基础之关键字,标识符,变量运算符以及程序流程控制
-
Java:使用synchronized和Lock对象获取对象锁
-
Java:使用synchronized和Lock对象获取对象锁
-
菜鸟学JAVA之——String及 基础数据类型的对象类型
-
java基础之基本数据类型对象包装类,StringBuffer
-
java基础之基本数据类型对象包装类,StringBuffer