Java线程:同步块

时间:2012-03-12 19:34:14

标签: java synchronization thread-safety synchronized-block

我需要一些帮助以确保我理解同步块。假设以下示例:

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并提前致谢。

3 个答案:

答案 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)

我会在submitObjectdeleteObject方法中对队列对象进行同步,这应该足够了,这意味着:

public submitObject(Object o){
    synchronized (theQueue) {
        ...
    }
}

public deleteObject(int objectId){
    synchronized (theQueue) {
        ...
    }
}

答案 2 :(得分:1)

您所做的相当于同步方法(public synchronized method()this本地变量queue同步,除了您必须记住每次都需要这样做你使用队列的时间。同步提交和删除方法会更安全.... 它还会从同步块中删除Object o = new Object()