我有两个可以访问对象的线程。使用synced(a),我在对象a上提供了锁定,因此现在每次线程上的线程都可以访问对象“ a”并对其进行修改。如果执行此代码,我们将得到1 2.在没有同步块的情况下,有时会得到2 2。(线程t1获取i并增加i现在线程t2获取i并递增,然后线程t1获得i并打印2,线程t2获取i并打印2) 如果我是对的,为什么我们不能使用synced(this)而不是synceded(a)?
public class Foo {
public static void main(String[] args) {
B b =new B();
b.start();
}
}
class B{
A a = new A();
Thread t1 =new Thread(new Runnable(){
public void run(){
synchronized(a){
a.increment();
}
}
});
Thread t2 =new Thread(new Runnable(){
public void run(){
synchronized(a){
a.increment();
}
}
});
public void start(){
t1.start();
t2.start();
}
}
class A{
int i = 0;
public void increment() {
i++;
System.out.println(i);
}
}
答案 0 :(得分:4)
如果我是真的,为什么我们不能使用synced(this)而不是synceded(a)?
如果您这样做:
public void run() {
synchronized (this) {
a.increment();
}
}
在这种情况下,this
是封闭的类实例,这里是一个匿名的Runnable对象,并且由于每个线程都有其自己的Runnable实例,因此您的同步位于单独的对象上,将无法正常工作。您必须在B.this
上同步才能正常工作。
public void run() {
synchronized (B.this) {
a.increment();
}
}
或对于所有同步块都相同的任何其他唯一对象。
或者,如果您想使用synchronized (this)
,则使用一个Runnable:
class B {
A a = new A();
Runnable r = new Runnable() {
public void run() {
synchronized (this) {
a.increment();
}
};
};
public void start() {
// t1.start();
// t2.start();
new Thread(r).start();
new Thread(r).start();
}
}
答案 1 :(得分:1)
另一种方法:
使方法increment
同步
public class Foo {
public static void main(String[] args) {
new B().start();
}
}
class B {
A a = new A();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
a.increment();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
a.increment();
}
});
public void start() {
t1.start();
t2.start();
}
}
class A {
int i = 0;
public synchronized void increment() { // <<<<<<<<
i++;
System.out.println(i);
}
}