public static void main(String[] args) { ThreadMain d = new ThreadMain(); A a = new A(); d.putA(a); d.main(a); } }class R implements Runnable{ Map<String,A> m;
R(Map<String,A> m){ this.m = m; } public void run() { A a = m.get("k"); System.out.println("before set A.b.value is:"+a.getB().getValue());
B b = new B(); b.setValue(8888); a.setB(b);
System.out.println("after set A.b.value is:"+a.getB().getValue()); } }class A { private B b; public B getB() { return b; } public void setB(B b) { this.b = b; } }class B{ private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
楼上的方法是有点取巧了,把多线程变成单线程运行了。 楼主的类里主线程里对A的实例做了改变,而在子线程里也对A的实例做了改变,所里这里做不了同步,应该把对A的修改全放在子线程里,把修改的代码块加上同步锁即可。如下:import java.util.HashMap; import java.util.Map;public class ThreadMain { Map<String,A> m = new HashMap<String, A>();
void putA(A a){ m.put("k", a); }
void main(A a) { int i = 10; while(i > 0) { // B b = new B(); // b.setValue(i); // a.setB(b);
R r = new R(m,i); Thread t = new Thread(r); t.start(); i--; } }
public static void main(String[] args) { ThreadMain d = new ThreadMain(); A a = new A(); d.putA(a); d.main(a); } }class R implements Runnable{ Map<String,A> m; int i;
R(Map<String,A> m,int i){ this.m = m; this.i = i; } public void run() { synchronized(ThreadMain.class){ A a = m.get("k"); B b = new B(); b.setValue(i); a.setB(b); System.out.println("before set A.b.value is:" + a.getB().getValue()); b = new B(); b.setValue(8888); a.setB(b); System.out.println("after set A.b.value is:" + a.getB().getValue()); } } }class A { private B b; public B getB() { return b; } public void setB(B b) { this.b = b; } }class B{ private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
请问为什么把46行换成如下: synchronized (this){ 输出的结果有可能就不对了,执行多次后,出现如下结果: before set A.b.value is:10 after set A.b.value is:8888 before set A.b.value is:8 after set A.b.value is:8888 before set A.b.value is:6 after set A.b.value is:8888 before set A.b.value is:9 after set A.b.value is:8888 before set A.b.value is:4 after set A.b.value is:8888 before set A.b.value is:2 after set A.b.value is:8888 before set A.b.value is:7 before set A.b.value is:8888 after set A.b.value is:8888 after set A.b.value is:8888before set A.b.value is:3 after set A.b.value is:8888 before set A.b.value is:1 after set A.b.value is:8888观察红色部分,显然,synchronized块执行的过程中,被其他线程打断了,难道对R对象加锁之后,没有完全锁住吗?请大哥分析一下
程序略作修改。ThreadMain 给R传m后,不要直接用this.m=m;因为是引用类型,两个m指向的是同一个实例,每个线程操作的都是你ThreadMain的m。R中m重新new一个,下面的a,b都要new,只复制个value。 import java.util.Map; import java.util.HashMap;public class ThreadMain { Map<String,A> m = new HashMap<String, A>();
void putA(A a){ m.put("k", a); } void main(A a) { int i = 10; while(i > 0) { B b = new B(); b.setValue(i); a.setB(b); R r = new R(m); Thread t = new Thread(r); t.start(); i--; } }
public static void main(String[] args) { ThreadMain d = new ThreadMain(); A a=new A(); d.putA(a); d.main(a); } }class R implements Runnable{ Map<String,A> m;
R(Map<String,A> m){ A a=m.get("k"); B b=a.getB(); int v=b.getValue(); B b1=new B(); b1.setValue(v); A a1=new A(); a1.setB(b1); this.m = new HashMap<String, A>(); this.m.put("k", a1); } public void run() {
A a = m.get("k"); System.out.println("before set A.b.value is:"+a.getB().getValue());
B b = new B(); b.setValue(8888); a.setB(b);
System.out.println("after set A.b.value is:"+a.getB().getValue()); } }class A { private B b; public B getB() { return b; } public void setB(B b) { this.b = b; } }class B{ private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
Map<String,A> m = new HashMap<String, A>();
void putA(A a){
m.put("k", a);
}
void main(A a) {
int i = 10;
while(i > 0) {
B b = new B();
b.setValue(i);
a.setB(b);
R r = new R(m);
Thread t = new Thread(r);
t.start();
i--;
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadMain d = new ThreadMain();
A a = new A();
d.putA(a);
d.main(a);
}
}class R implements Runnable{
Map<String,A> m;
R(Map<String,A> m){
this.m = m;
} public void run() {
A a = m.get("k");
System.out.println("before set A.b.value is:"+a.getB().getValue());
B b = new B();
b.setValue(8888);
a.setB(b);
System.out.println("after set A.b.value is:"+a.getB().getValue());
}
}class A {
private B b;
public B getB() {
return b;
} public void setB(B b) {
this.b = b;
}
}class B{
private int value; public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
}
}
楼主的类里主线程里对A的实例做了改变,而在子线程里也对A的实例做了改变,所里这里做不了同步,应该把对A的修改全放在子线程里,把修改的代码块加上同步锁即可。如下:import java.util.HashMap;
import java.util.Map;public class ThreadMain {
Map<String,A> m = new HashMap<String, A>();
void putA(A a){
m.put("k", a);
}
void main(A a) {
int i = 10;
while(i > 0) {
// B b = new B();
// b.setValue(i);
// a.setB(b);
R r = new R(m,i);
Thread t = new Thread(r);
t.start();
i--; }
}
public static void main(String[] args) {
ThreadMain d = new ThreadMain();
A a = new A();
d.putA(a);
d.main(a);
}
}class R implements Runnable{
Map<String,A> m;
int i;
R(Map<String,A> m,int i){
this.m = m;
this.i = i;
} public void run() {
synchronized(ThreadMain.class){
A a = m.get("k");
B b = new B();
b.setValue(i);
a.setB(b);
System.out.println("before set A.b.value is:" + a.getB().getValue()); b = new B();
b.setValue(8888);
a.setB(b); System.out.println("after set A.b.value is:" + a.getB().getValue());
}
}
}class A {
private B b;
public B getB() {
return b;
} public void setB(B b) {
this.b = b;
}
}class B{
private int value; public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
}
}
原代码这么写是为了方便Map作为全局缓存对里面的对象根据不同的条件赋值再在其他类里面使用,我觉得也有点别扭,而且现在在多线程的情况下又出现了好麻烦的bug
synchronized (this){
输出的结果有可能就不对了,执行多次后,出现如下结果:
before set A.b.value is:10
after set A.b.value is:8888
before set A.b.value is:8
after set A.b.value is:8888
before set A.b.value is:6
after set A.b.value is:8888
before set A.b.value is:9
after set A.b.value is:8888
before set A.b.value is:4
after set A.b.value is:8888
before set A.b.value is:2
after set A.b.value is:8888
before set A.b.value is:7
before set A.b.value is:8888
after set A.b.value is:8888
after set A.b.value is:8888before set A.b.value is:3
after set A.b.value is:8888
before set A.b.value is:1
after set A.b.value is:8888观察红色部分,显然,synchronized块执行的过程中,被其他线程打断了,难道对R对象加锁之后,没有完全锁住吗?请大哥分析一下
而synchronized(ThreadMain.class)是对全局加锁,所以能到到达互斥的效果!
import java.util.Map;
import java.util.HashMap;public class ThreadMain {
Map<String,A> m = new HashMap<String, A>();
void putA(A a){
m.put("k", a);
}
void main(A a) {
int i = 10;
while(i > 0) {
B b = new B();
b.setValue(i);
a.setB(b);
R r = new R(m);
Thread t = new Thread(r);
t.start();
i--;
}
}
public static void main(String[] args) {
ThreadMain d = new ThreadMain();
A a=new A();
d.putA(a);
d.main(a);
}
}class R implements Runnable{
Map<String,A> m;
R(Map<String,A> m){
A a=m.get("k");
B b=a.getB();
int v=b.getValue();
B b1=new B();
b1.setValue(v);
A a1=new A();
a1.setB(b1);
this.m = new HashMap<String, A>();
this.m.put("k", a1);
} public void run() {
A a = m.get("k");
System.out.println("before set A.b.value is:"+a.getB().getValue());
B b = new B();
b.setValue(8888);
a.setB(b);
System.out.println("after set A.b.value is:"+a.getB().getValue());
}
}class A {
private B b;
public B getB() {
return b;
} public void setB(B b) {
this.b = b;
}
}class B{
private int value; public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
}
}
补充一点,this代表的是R对象,因为每次循环都是new R(), 所以synchronized(this)是分别对每个R对象加锁,这些锁之间互不干扰,所以每个线程都能拿到自己的R对象锁然后执行synchronized块里的代码,这样就是锁不住的原因;如果R对象是单例的,每次循环拿到的都是同一个R对象,那么synchronized(this)就是对单例的那个R对象加锁,自始至终只有这一个锁,这样的话每个线程要想执行synchronized块里的代码,必须得拿到那个唯一的R对象锁,这样就起到锁的作用了。
以上是我个人的理解,有不对的地方请指出,谢谢!