我需要一些帮助以确保我理解同步块。假设以下示例:
public class ThreadStarter {
public static void main(String[] args) {
Queue queueObject = new Queue();
ThreadA thread1 = new ThreadA(queueObject);
ThreadA thread2 = new ThreadA(queueObject);
ThreadB thread3 = new ThreadB(queueObject);
ThreadB thread4 = new ThreadB(queueObject);
thread1.start();
thread2.start();
}
}
public class Queue {
Object[] the theQueue;
public Queue(int size){
theQueue = new Object[size];
}
public submitObject(Object o){
/* add Object to the queue */
}
public deleteObject(int objectId){
/*delete Object from the queue */
}
}
public class ThreadA extends Thread {
private Queue queue;
public ThreadA(Queue queue){
this.queue = queue;
}
public void run() {
while(!isInterrupted()){
synchronized(queue) {
Object o = new Object
queue.submitObject(o);
/* do some other stuff */
}
try {
sleep((int)(Math.random()*1000));
} catch (interruptedException) {
Thread.currentThread().interrupt;
}
synchronized(queue) {
/* do some other stuff on the queue */
}
}
}
}
public class ThreadB extends Thread {
private Queue queue;
public ThreadB(Queue queue){
this.queue = queue;
}
public void run() {
while(!isInterrupted()){
synchronized(queue) {
queue.deleteObject(o);
/* do some other stuff */
}
try {
sleep(1000);
} catch (interruptedException) {
Thread.currentThread().interrupt;
}
}
}
}
我的问题是,是否足以同步ThreadA中的整个队列对象以将对象提交到队列类,以确保安全?我在ThreadB中做了同样的事情来从队列中删除一个对象。或者我是否必须同步Queue类中的submitObject()和deleteObject()方法?
根据我的理解,如果我将整个Queue类锁定在如上所示的线程中,我应该安全 - 对吧?
greetZ并提前致谢。
答案 0 :(得分:2)
你需要做的就是确保没有两个线程无法进入submitObject& deleteObjecct同时。要实现这一点,只需声明这些方法是同步的。 在这种情况下,类之间共享的队列对象将阻止2个线程在它同步的块上。
此外,如果您想要某种阻止机制,例如:
“如果一个线程要删除一个对象,它必须等待,如果有的话 队列中没有这样的对象。“
那么你需要做的不仅仅是以这种方式同步:两个方法应该仍然是同步的,但是队列中使用this.wait应该停止输入deleteObject的线程,直到一个对象变为可用:
public synchronized deleteObject() {
while( isEmpty() ) {
try {
wait();
} catch( Exception ex ) {
ex.printStackTrace();
}//catch
}//while
//actually do delete object.
...
}//met
然后submitObject应该通过执行以下操作来通知处于等待状态的线程:
public synchronized submitObject() {
//do put object
...
notifyAll();
}//met
并且您还可以跨角色并在两种方法中添加一些代码,例如,如果队列已满,则允许阻止提交者,并在队列中剩余一些空间时通知。
答案 1 :(得分:1)
我会在submitObject
和deleteObject
方法中对队列对象进行同步,这应该足够了,这意味着:
public submitObject(Object o){
synchronized (theQueue) {
...
}
}
public deleteObject(int objectId){
synchronized (theQueue) {
...
}
}
答案 2 :(得分:1)
您所做的相当于同步方法(public synchronized method()
与this
本地变量queue
同步,除了您必须记住每次都需要这样做你使用队列的时间。同步提交和删除方法会更安全....
它还会从同步块中删除Object o = new Object()
。