我对对象锁定感到困惑。 下面的类有4个方法,方法addB()是同步的。
在我的scienario中,有4个主题。当一个线程2访问addB()方法(它在Test对象上创建一个锁)时,是否会有其他任何线程同时访问addC()或addD()?
对象锁一次只允许一个线程吗?
class Test{
private Integer a;
private Integer b;
private Integer c;
private Integer d;
public void addA(){
synchronized(a) {
a++;
}
}
public synchronized void addB(){
b++;
}
public void addC(){
c++;
}
public void addD(){
d++;
}
}
编辑: 我有3个线程(t1,t2和t3),每个线程将访问addB(),addC()和addD()。如果线程t1访问方法addB(),可以同时线程t2访问addC()方法吗?如果不是t2状态会是什么?
class Test{
private Integer a;
private Integer b;
private Integer c;
private Integer d;
public void addA(){
synchronized(a) {
a++;
}
}
public synchronized void addB(){
b++;
}
public synchronized void addC(){
c++;
}
public synchronized void addD(){
d++;
}
}
答案 0 :(得分:4)
锁确实一次只允许一个线程,但不同的锁不会相互影响。
在您的示例中,您有两个锁 - 一个位于属于a
的互斥锁上,另一个位于属于this
的互斥锁上(当您使用synchronized
关键字时,这是隐式的,正如你在帖子中正确提到的那样)。
因此对addB()
的调用将被同步,但不会阻止对任何其他方法的调用。如果一个线程持有this
上的锁,则另一个线程可以保持a
上的锁,并且多个其他线程可以同时执行addC()
和addD()
。
修改:除此之外,如果您真的使用AtomicInteger
,您可能有兴趣了解Integer
课程。它们提供原子操作,因此您无需担心它们之间的同步。
答案 1 :(得分:1)
您的代码中有两个锁,只有一个Thread可以遍历Lock#1或Lock#2。两个锁都是独立的,这意味着它们不会相互排除线程。
锁定#1在对象上同步
public void addA(){
synchronized(a) {
a++;
}
}
lock#2在测试实例上同步(this)
public synchronized void addB(){
b++;
}
addC()和addD()根本没有锁,任何数量的线程都可以同时访问它们。
答案 2 :(得分:1)
同步块只是一个环境,您可以将其作为reentrant lock“执行”的对象视为对象。实际上,只允许一个线程同时锁定一个对象。
方法C和D永远不会锁定,并且可以随时由任何线程执行。
正如其他人所指出的,当你执行a++
时,你会创建一个新的Integer实例。
答案 3 :(得分:0)
Lock提供了一种同步线程的机制。这意味着在同一时间点只有一个线程可以访问对象的AddB方法。 除非在代码完成后释放锁,否则下一次代码迭代无法进入该块。
答案 4 :(得分:0)
锁定线程取决于所用对象的实例 e.g:
class MyClass extends Thread{
Test instanceObj=null;
public MyClass(Test obj){
instanceObj=obj;
}
public void run(){
obj.addB();
}
}
addB()函数可以重写为
public void addB(){
synchronized(this){
//func
}
}