Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中同步块的部分执行_Java_Multithreading_Synchronization_Thread Synchronization - Fatal编程技术网

java中同步块的部分执行

java中同步块的部分执行,java,multithreading,synchronization,thread-synchronization,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)并执行第1行和第2行。然后线

我只是好奇有没有可能一个线程T1说部分执行同步块,然后释放对象上的锁,另一个线程T2执行相同的块?大概是这样的:

line1: synchronized(this){
line2:  if(INSTANCE == null)
line3:   INSTANCE = new Object(); //say a variable is initialized
line4:  return INSTANCE;
line5: }
线程T1是否可能获取当前对象的锁(
this
)并执行第1行和第2行。然后线程T1被线程T2抢占,T1释放锁,T2获取
这个
上的锁,并执行相同的块(所有行1到5)。然后线程T1再次获取锁并继续从第3行执行

基本上,T1会将
实例
视为null,T2也会如此,每个实例都会创建一个新对象

如果这不可能,有人能解释为什么不可能吗

增编:


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

线程抢占不会导致被抢占的线程释放其锁。如果真是这样,锁将一文不值。
synchronized
块的全部要点是,它将禁止其他线程在同一对象上同步,直到线程释放锁(通过保持
synchronized
块)。

线程抢占不会导致被抢占的线程释放其锁。如果真是这样,锁将一文不值。
synchronized
块的全部要点是,它将禁止其他线程在同一对象上同步,直到线程释放锁(通过离开
synchronized
块).

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


请参阅此处的更多信息:

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


请参阅此处的详细信息:

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


当然,可以编写代码,允许访问实例或字段而不必使用锁,但这是一个编码错误。原始线程也可能提前退出块(比如抛出异常)——这会释放锁,其他线程可以正常继续。

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

当然,可以编写代码,允许访问实例或字段而不必使用锁,但这是一个编码错误。原始线程也可能提前退出块(比如抛出异常)——这会释放锁,其他线程可以正常继续。

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

关于如何实现它的一个很好的教程

请查看以下代码:

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
基本上你可以使用对象。锁定对象允许您逐行顺序应用和释放多个锁定

关于如何实现它的一个很好的教程

请查看以下代码:

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

除非在第一个线程对同步对象调用
wait()
的特殊情况下为True。除非在第一个线程对同步对象调用
wait()
的特殊情况下为True。感谢您的回答。我的问题有点误导。我想问的是,一旦线程执行了一个同步块,它是否有可能在整个块执行之前释放锁?嗨,你的答案与这个问题无关,会让其他正在寻找答案的人感到困惑。我不是在寻找如何实现锁或重入锁;线程在完成同步块之前可以释放锁。Thanks@SubhomoySikdar这个问题的措辞是根据我回答的版本修改的。你在这里输入capslock来证明这一点,而且在它被回答四年后,人们通常不会超出公认的答案,担心人们被误导。这里有一个评论区来评论这个问题。你好……我没有修改我问题的措辞……我只是解释一下