java中同步块的部分执行
我只是好奇有没有可能一个线程T1说部分执行同步块,然后释放对象上的锁,另一个线程T2执行相同的块?大概是这样的: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行。然后线
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来证明这一点,而且在它被回答四年后,人们通常不会超出公认的答案,担心人们被误导。这里有一个评论区来评论这个问题。你好……我没有修改我问题的措辞……我只是解释一下