我有两个并发运行的线程,一个主线程和一个实现Runnable
的侦听器。
主线程和侦听器都有一个关键部分,特别是在主类中运行的Manager类中的方法getObjectList(String)
和在侦听器线程中运行的handleNewObjects(String, List<Object>)
。
我目前的计划是让getObjectList()
成为同步方法:
class Manager {
protected synchronized getObjectList() {
// Do critical section stuff
}
}
并使handleNewObjects()
看起来像这样
class Listener implements Runnable {
private final Manager myManager;
handleNewObjects() {
synchronized (myManager) {
// Do critical section stuff
}
}
}
这会确保我的关键部分不会同时运行吗? 我应该以其他方式同步吗?
答案 0 :(得分:1)
这会确保我的关键部分永远不会同时运行吗?
是的,但正如Quirliom所说,确保它们是同一个物体。如果您正在使用任何框架,请注意框架创建的代理。
我应该以其他方式同步吗?
生产者 - 消费者设置非常普遍。当你有多个时,事情会变得棘手。您可以查看built into the platform的某些类,而不是自己重新创建它。来自Javadocs(不完全是你正在做的,但接近):
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
答案 1 :(得分:1)
如果getObjectList()
是同步方法,myManager
中的Listener
与将修改共享对象集的实例相同Manager
个实例,那么是的,它会起作用。
很难说在不了解现有代码之间的关系的情况下知道是否有更好的解决方案,但这种方法可能会被视为有些脆弱。对Manager
锁定对象的更改将导致Listener
不再是线程安全的,如果共享对象中的两个关键部分修改已经存在于Manager中,您也可以让Listener调用另一个在经理中同步,说myManager.handleNewObjects()
。
对于管理器锁定的对象的更改,我的意思是Manager来自:
protected synchronized getObjectList() {
// Do critical section stuff
}
到
protected getObjectList() {
synchronized (myPrivateFinalLockObject) {
// Do critical section stuff
}
}
或
protected getObjectList() {
delegatingWorkToSomeOtherThreadSafeObject.getObjectList();
}
然后Listener不再是线程安全的,因为它不再锁定它在同一个对象上的关键部分。
答案 2 :(得分:0)
假设getObjectsList是一个没有更新的检索方法,您可以利用ReadWriteLocks改进并发性。这里handle *方法是更新基础列表的方法。请参阅: http://ilkinbalkanay.blogspot.com/2008/01/readwritelock-example-in-java.html