如果我有两种方法不能在一个 class 中同时发生在不同的线程上,如何锁定它?
if i have two methods that cannot happen simultaneously in one class on separate threads, how to lock it?
如果我有一个 class 有 2 个方法,比如 setA
和 setB
有 synchronized
但它们在同一个对象上不同步,我怎么办锁定它,这样如果 class 有两个实例,方法 setA
和 setB
就不能同时发生?
您仍然可以在您创建的 class 中的另一个对象上进行同步。
Object lock = new Object();
然后只在锁定对象上同步。
如果您想更深入地了解它,可以使用 util.concurrency 库。
检查信号量或锁存器,取决于你想用你的 setA 和 setB
做什么
在单个静态引用上同步它们。 private static final Object lock = new Object ()
就可以了,Will 就可以 TheClass.class。
这也意味着没有两个线程可以同时调用 setA,即使没有人在调用 setB。如果这不可接受,您可以使用(静态)读写锁进行更细粒度的访问。 setA使用读锁,setB使用写锁;这意味着任意数量的线程都可以调用 setA,但只有一个线程可以调用 setB。您可能 不 希望反过来也成立,因为这很容易出现死锁。
多种方式。
1) 您可以同步方法:public synchronized void setA()
这样做意味着一次只能有一个线程进入该方法(好的和坏的)
2) 更好的解决方案是使用 ReentrantLock
:
ReentrantLock lock = new ReentrantLock();
void public void setA() {
lock.lock();
try {
//Do Something
}
finally {
lock.unlock();
}
}
还有其他方法。
您可以查看 Java 并发教程:
https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
另一个不错的帖子:
http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
祝你好运!
简而言之,您可以在两种方法的主体中使用一个 synchronized (lockObj) {...}
块,并使用相同的 lockObj
实例。
class MyClass {
private final Object lock;
public MyClass(Object lock) {
this.lock = lock;
}
public void setA() {
synchronized (lock) {
//...
}
}
public void setB() {
synchronized (lock) {
//...
}
}
}
注意事项:
- 锁不需要是静态的。如何提供它取决于您的实现。但是如果您希望每个
MyClass
实例都必须使用 相同的 锁实例以防止线程同时执行它们的块。
- 在这种情况下您不能使用同步方法,因为每个非静态
synchronized
方法都将在此实例的监视器上使用它。
- 如果要访问其他实例成员,也不能使用
static synchronized
方法。
如果我有一个 class 有 2 个方法,比如 setA
和 setB
有 synchronized
但它们在同一个对象上不同步,我怎么办锁定它,这样如果 class 有两个实例,方法 setA
和 setB
就不能同时发生?
您仍然可以在您创建的 class 中的另一个对象上进行同步。
Object lock = new Object();
然后只在锁定对象上同步。
如果您想更深入地了解它,可以使用 util.concurrency 库。 检查信号量或锁存器,取决于你想用你的 setA 和 setB
做什么在单个静态引用上同步它们。 private static final Object lock = new Object ()
就可以了,Will 就可以 TheClass.class。
这也意味着没有两个线程可以同时调用 setA,即使没有人在调用 setB。如果这不可接受,您可以使用(静态)读写锁进行更细粒度的访问。 setA使用读锁,setB使用写锁;这意味着任意数量的线程都可以调用 setA,但只有一个线程可以调用 setB。您可能 不 希望反过来也成立,因为这很容易出现死锁。
多种方式。
1) 您可以同步方法:public synchronized void setA()
这样做意味着一次只能有一个线程进入该方法(好的和坏的)
2) 更好的解决方案是使用 ReentrantLock
:
ReentrantLock lock = new ReentrantLock();
void public void setA() {
lock.lock();
try {
//Do Something
}
finally {
lock.unlock();
}
}
还有其他方法。 您可以查看 Java 并发教程: https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
另一个不错的帖子: http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
祝你好运!
简而言之,您可以在两种方法的主体中使用一个 synchronized (lockObj) {...}
块,并使用相同的 lockObj
实例。
class MyClass {
private final Object lock;
public MyClass(Object lock) {
this.lock = lock;
}
public void setA() {
synchronized (lock) {
//...
}
}
public void setB() {
synchronized (lock) {
//...
}
}
}
注意事项:
- 锁不需要是静态的。如何提供它取决于您的实现。但是如果您希望每个
MyClass
实例都必须使用 相同的 锁实例以防止线程同时执行它们的块。 - 在这种情况下您不能使用同步方法,因为每个非静态
synchronized
方法都将在此实例的监视器上使用它。 - 如果要访问其他实例成员,也不能使用
static synchronized
方法。