在java中部分执行同步块

时间:2014-12-18 20:42:18

标签: java multithreading synchronization thread-synchronization

我只是好奇,是否有线程T1说部分地执行同步块然后释放对象的锁定而另一个线程T2执行相同的块?像这样:

line1: synchronized(this){
line2:  if(INSTANCE == null)
line3:   INSTANCE = new Object(); //say a variable is initialized
line4:  return INSTANCE;
line5: }

线程T1是否可能获取当前对象(this)的锁并执行line1和line2。然后线程T1被线程T2抢占,T1释放锁定,T2获取this上的锁定并执行相同的块(所有行1到5)。然后线程T1再次获取锁定并继续从第3行执行?

基本上,T1会将INSTANCE视为空,因此T2将会创建一个新的对象。

如果不可能,有人可以解释原因吗?

附录:

感谢大家的回答。我的问题有点误导。我要问的是,一旦一个线程执行一个同步块,它可以在整个块执行之前释放锁(不是通过显式调用wait()而是通过进程,CPU依赖的东西)?在JLS或JVM中是否有合同保证一旦线程开始执行同步块,对象的锁定直到块结束才会被释放?我的理解是同步保证没有2个线程可以同时执行块(或其他同步的方法/块),但锁是否保持到块到达块结束?它有点明显,但它是否在JLS中指定?

4 个答案:

答案 0 :(得分:4)

线程抢占不会导致抢占的线程释放其锁定。如果确实如此,锁将毫无价值。 synchronized块的重点是它将禁止其他线程在同一对象上同步,直到线程释放锁(通过离开synchronized块)。

答案 1 :(得分:1)

即使线程被抢占,它也不会释放锁定。锁仍然存在。如果另一个线程出现,它将阻塞(停止运行)直到锁被释放,即使原始线程在释放锁之前被抢占了几次。基本上几乎任何类型的锁都会在堆中有一些存储空间,这些存储空间会被写入以指示存在锁定。它是永久性的,直到线程或系统写入不同的值来指示锁是空闲的。

当然可以编写允许访问实例或字段而无需锁定的代码,但这是编码错误。原始线程也可以提前退出块(比如抛出异常) - 这会释放锁定,其他线程可以正常继续。

答案 2 :(得分:0)

我很确定第二个线程在第一个线程执行整个块之前不可能进入synchronize块。在获取对象的锁定时,将阻止尝试输入同步代码的所有其他线程。

在此处查看更多信息:http://tutorials.jenkov.com/java-concurrency/synchronized.html

答案 3 :(得分:-1)

基本上你可以使用Locks个对象。锁定对象可以允许您逐行顺序地应用和释放多个锁定上的锁定。

关于如何实施它的非常好的教程here

查看以下代码:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;




public class test2{

    private static Object instance = null;
    private static test2 t = new test2();
    private static Lock lock = new ReentrantLock();
    public static void main(String[] args) {

        A a = new A();
        B b = new B();
        a.setName("Thread-A");
        b.setName("Thread-B");
        a.start();
        b.start();
    }

    public Object getObj(){
        try {
            lock.lock();
            System.out.println("Begin Current thread:  "+ Thread.currentThread().getName());
            if(instance == null){
                if(Thread.currentThread().getName().equalsIgnoreCase("Thread-A")){
                    lock.unlock();
                    while(instance==null){
                        System.out.println(Thread.currentThread().getName() +"  :  instance is null");
                    }
                    while(true){
                        if(!lock.tryLock()){
                           System.out.println(Thread.currentThread().getName() + " waiting for re lock");
                        }else{
                           lock.lock();
                           break;
                       }
                    }
                }
                instance =new Object();
                System.out.println("End Current thread:  "+ Thread.currentThread().getName());
                if (((ReentrantLock) lock).isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return instance;
    }


    public static class A extends Thread{
        @Override
        public void run() {
            while(true){
                if(t.getObj() != null){
                    break;
                }
            }
        }
    }

    public  static class B extends Thread{
        @Override
        public void run() {
            while(true){
                if(t.getObj() != null){
                    break;
                }
            }
        }
    }

}

<强>输出

Begin Current thread:  Thread-A
Thread-A  :  instance is null
Begin Current thread:  Thread-B
Thread-A  :  instance is null
End Current thread:  Thread-B
Thread-A waiting for re lock
End Current thread:  Thread-A