public class Service {
private String lock = "123"; public void test() {
synchronized (lock) {
try {
System.out.println(Thread.currentThread().getName() + " - start;");
// 在这里改变lock对象
lock = "456 "; Thread.sleep(600);
System.out.println(Thread.currentThread().getName() + " - end;");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}/**
* main方法
*/
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
ThreadA a = new ThreadA(service);
ThreadB b = new ThreadB(service);
a.setName("a");
b.setName("b");
a.start();
// 在这里将主线程睡眠一段时间,就会出现不一样的结果?????(请问是为什么)
Thread.sleep(200);
b.start();
}
}/**
* ThreadA
*/
class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
this.service = service;
} @Override
public void run() {
super.run(); service.test();
}
}/**
* ThreadB
*/
class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
this.service = service;
} @Override
public void run() {
super.run(); service.test();
}
}
解决方案 »
- 程序报"java.io.EOFException"
- 求java数据库连接和登录按钮的方法
- 金字塔如何实现
- 求一正则表达式解析json对象
- 关于数据库数据导出csv文件,用制表符分割出现问题。请大家帮忙看看
- 问一个关于synchronized(this)
- 什么是public Main()错误?
- 怎样解决运行javaGUI程序后,整个窗体就没有相应的问题
- 救命:卸了JB9再装JB8,然后所有工程都不能通过编译了
- 求Java代码:List<Student> ls中有学生id和课程:11,语文;11,数学;14,数学;14,物理;怎样可以统计每个学生id所选修了几门课
- 为什么我点了一个程序的run as后面的Java application程序没有运行出或任何结果,而且这个程序仅仅是最简单的hello world,
- jmenu 下拉菜单,位置应该如何 调整?
synchronized (lock)这句话其实是锁住的常量池中的"123"对象的对象头
在A线程中修改了lock = "456 ";
B线程再次进入synchronized (lock)这个代码块时lock = "456 ",
发现常量池中的"456"对象没有被锁住,所以还是可以进入synchronized (lock)代码块的
如果第一个抢到了就是a-start反之亦是
本来b线程也要抢占执行权,但是程序在睡眠
这个时候改变锁的对象456没有锁住
b线程肯能又抢到了执行权
但是因为时间的关系你运行的时候看不出来
你暂停了的时间就会程序出错的几率更大,也就是你提问的原因
try {
System.out.println(Thread.currentThread().getName() + " - start;");
// 在这里改变lock对象
lock = "456 ";
这段有问题的,。一般同步的对象都必须是finally类型的,不变的。
如果你把他改变了,后面就没有线程可以获取到同步对象了。