synchronized块的问题,main方法主线程没有被synchronized阻塞

zxp123549440 2017-08-31 04:07:24
Sync2 s = new Sync2();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
s.test();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
s.test2();
}
});
thread.start();
thread2.start();
synchronized(s.getObj()){
System.out.println("锁我了么");
}
上面是双线程同时调用s对象的方法,test1、test2同时都锁了Sync2类静态成员,而main方法再启动两个线程后,又对Sync2类静态成员加了同步块,理论来讲,main方法线程、thread2都会阻塞,等待thread释放后才能获得object对象的锁,但是测试确是先输出了"锁我了么"


public class Sync2 {
public static Object getObj() {
return obj;
}


public static void setObj(Object obj) {
Sync2.obj = obj;
System.out.println("被设置");
}


private static Object obj = new Object();

public void test() {
synchronized(obj){
System.out.println("test开始..");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test结束..");
}
}


public void test2() {
synchronized(obj){
System.out.println("test2开始..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test2结束..");
}
}
}
...全文
278 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
pilnyun335857183 2017-08-31
  • 打赏
  • 举报
回复
引用 4 楼 zxp123549440 的回复:
[quote=引用 3 楼 pilnyun335857183 的回复:] Thread对象的start方法调用后线程是处于就绪状态,只有操作系统为线程分配了时间片后线程才会得到执行。从你上面的结果来看,thread及thread2在start调用后都没有立即获取到时间片,从而是main线程首先获取到了s中的对象锁。
您说的是正确的,我在main方法锁关键字前加了一点休眠,可以看出来thread先获得了锁,执行完了,main方法才获得了锁,并进行输出 其实最开始我是被另一个问题所困惑,这个只是自己写个例子测试一下 下面这段代码,可以实现类似CountDownLatch的功能,当上面的线程执行完毕,整个线程才结束 main方法加了synchronized块,也就获得completeSignal对象的锁,thread运行中遇到synchronized应该阻塞,可是程序却顺利的 进入了synchronized块,并把completeSignal.notifyAll()了,这个您清楚是怎么回事么?
final Object completeSignal = new Object();
		Thread thread = new Thread("worker-thread") {
			public void run() {
				try {
					Thread.sleep(3000);
					System.out.println("执行");
				} catch (Exception e) {
					e.printStackTrace();
				}
				
				synchronized (completeSignal) {
					completeSignal.notifyAll();
				}
			}
		};
		
		
		synchronized (completeSignal) {
			thread.start();
			completeSignal.wait();
			System.out.println("执行完了");
		}
[/quote] 很明显你在main线程中调用了completeSignal.wait(); wait与sleep方法时有区别的两者都会使得线程挂起但是wait会释放锁。
zxp123549440 2017-08-31
  • 打赏
  • 举报
回复
疑惑已经查明,有一个知识盲点: 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备 感谢一下博主的分享:http://www.cnblogs.com/hongten/p/hongten_java_sleep_wait.html 我在他的例子基础上又添加了一些测试,两个线程来回换锁拥有权,详见:https://git.oschina.net/zxporz/zxp-thread-test.git org.zxp.thread.wait.TestD org.zxp.thread.wait.TestE
luck2662715 2017-08-31
  • 打赏
  • 举报
回复
关于synchronized锁代码块:()内的对象取得只是一个地址,可以理解为给锁取个名字,真正锁上的内容只有这个名字的锁所包含的代码块,也就是System.out.println这一句而已。如果其他代码也用了synchronized()同样的名字的锁,他们将都是互斥的。
zxp123549440 2017-08-31
  • 打赏
  • 举报
回复
引用 3 楼 pilnyun335857183 的回复:
Thread对象的start方法调用后线程是处于就绪状态,只有操作系统为线程分配了时间片后线程才会得到执行。从你上面的结果来看,thread及thread2在start调用后都没有立即获取到时间片,从而是main线程首先获取到了s中的对象锁。
您说的是正确的,我在main方法锁关键字前加了一点休眠,可以看出来thread先获得了锁,执行完了,main方法才获得了锁,并进行输出 其实最开始我是被另一个问题所困惑,这个只是自己写个例子测试一下 下面这段代码,可以实现类似CountDownLatch的功能,当上面的线程执行完毕,整个线程才结束 main方法加了synchronized块,也就获得completeSignal对象的锁,thread运行中遇到synchronized应该阻塞,可是程序却顺利的 进入了synchronized块,并把completeSignal.notifyAll()了,这个您清楚是怎么回事么?
final Object completeSignal = new Object();
		Thread thread = new Thread("worker-thread") {
			public void run() {
				try {
					Thread.sleep(3000);
					System.out.println("执行");
				} catch (Exception e) {
					e.printStackTrace();
				}
				
				synchronized (completeSignal) {
					completeSignal.notifyAll();
				}
			}
		};
		
		
		synchronized (completeSignal) {
			thread.start();
			completeSignal.wait();
			System.out.println("执行完了");
		}
pilnyun335857183 2017-08-31
  • 打赏
  • 举报
回复
Thread对象的start方法调用后线程是处于就绪状态,只有操作系统为线程分配了时间片后线程才会得到执行。从你上面的结果来看,thread及thread2在start调用后都没有立即获取到时间片,从而是main线程首先获取到了s中的对象锁。
zxp123549440 2017-08-31
  • 打赏
  • 举报
回复
补充一下,后台输出了: 锁我了么 test2开始.. test2结束.. test开始.. test结束.. 先输出锁我了么
soton_dolphin 2017-08-31
  • 打赏
  • 举报
回复
你如果想让 main 线程最后执行完,可以用 thread.join(); thread2.join(); System.out.println("main finished");

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧