当synchronized使用过多时,可能会造成死锁,那么死锁到底是怎么一回事呢。先看下面的代码,实现死锁:
//死锁的实现
class A
{
public void get(){
System.out.println("A说:我开始启动了,B,给我你的资源");
}
public void say(){
System.out.println("A获得资源");
}
}
class B
{
public void get(){
System.out.println("B说:我开始启动了,A,给我你的资源");
}
public void say(){
System.out.println("B获得资源");
}
}
class MyThread implements Runnable
{
public static A a = new A();
public static B b = new B();
public boolean flag = false;
public void run(){
if(flag){
synchronized(a){
a.get();
try{
Thread.sleep(500);
}catch(InterruptedException e){}
synchronized(b){ //此同步代码块在另一同步代码块里
a.say();
}
}
}else{
synchronized(b){
b.get();
try{
Thread.sleep(500);
}catch(InterruptedException e){}
synchronized(a){ //此同步代码块在另一同步代码块里
b.say();
}
}
}
}
}
public class Demo24
{
public static void main(String args[]){
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.flag=true;
mt2.flag=false;
Thread th1 = new Thread(mt1);
Thread th2 = new Thread(mt2);
th1.start();
th2.start();
}
}
以上代码由于 synchronized 的同步造成了死锁,死锁是两个或多个线程同时等待对方的完成,而程序无法继续执行。在解释代码前,首先要明白synchronized到底是怎么一回事。synchronized 定义同步,那么同步的什么,什么和什么同步了?
首先,我们得知道,什么是锁。在java中,每一个对象都有一个内部锁,如果以方法或代码块用 synchronized 进行声明,那么对象的锁将保护整个方法或代码块,要调用这个方法或者执行这个代码块,必须获得这个对象的锁。而且,任何时候都只能有一个线程对象执行被保护的代码
在以上代码中,在线程th1启动后,他就获得了a的锁,同时当其休眠完毕,求会申请获得b的锁,而此时,他的a锁没有放弃。在线程th2启动后,他就获得了b的锁,同时当其休眠完毕,求会申请获得a的锁,而此时,他的b锁没有放弃。
两方都握有自己的锁不放弃,而同时申请另一方的锁,所以,此时就造成了死锁。
同步,同步的就是线程和对象,将线程和对象进行绑定,获取对象的锁。
注意:通过以上代码可以发现,死锁的必要条件是不放弃已有的锁,而同时申请新锁。所以,要想实现死锁,就会有synchronized的嵌套。
这样才能同时操作两个以上的锁,从而造成死锁。
分享到:
相关推荐
在上面的代码中,我们可以看到两个线程 th1 和 th2,它们都尝试获取 a 和 b 的锁,但是由于 synchronized 的嵌套使用,导致了死锁的发生。死锁是指两个或多个线程同时等待对方的完成,而程序无法继续执行。在这个...
这个例子中,我们将会深入探讨死锁的产生、识别以及如何避免它。 首先,让我们理解什么是死锁。在多线程环境中,当两个线程A和B分别持有对方需要的资源并等待对方释放时,就会发生死锁。例如,线程A持有资源1并请求...
给定的例子展示了两个线程(t1 和 t2)和两个对象(resource1 和 resource2)之间的死锁情况: ```java public class Deadlock { public static void main(String[] args) { final Object resource1 = "resource1...
在这个例子中,`thread1`和`thread2`分别按照`resource1 -> resource2`和`resource2 -> resource1`的顺序获取资源,避免了循环等待,从而消除了死锁的可能性。 总的来说,理解并正确使用`synchronized`关键字是防止...
1. 避免嵌套锁定:在上面的例子中,如果我们避免了嵌套锁定,那么就不会出现死锁。 2. 使用Lock对象:Java提供了Lock对象,可以用来代替synchronized关键词,避免死锁的出现。 3. 使用atomic变量:使用atomic变量...
- **避免嵌套锁**:尽量减少使用嵌套锁的数量。 - **使用超时**:尝试获取锁时设置超时时间,如果在规定时间内无法获取锁,则放弃操作。 ```java if (lock.tryLock(5, TimeUnit.SECONDS)) { try { // 执行临界区...
`synchronized`关键字还与`wait()`, `notify()`和`notifyAll()`方法配合使用,用于线程间的通信和同步。这些方法必须在`synchronized`代码块或方法中调用,否则会抛出`IllegalMonitorStateException`。 8. **...
在这个例子中,`outerMethod`和`innerMethod`都被声明为`synchronized`。当一个线程调用`outerMethod`并获得锁后,它可以无阻塞地进入`innerMethod`,因为这两个方法都由同一个对象的锁保护。如果`synchronized`不...
为了避免死锁,我们可以遵循以下原则:避免嵌套锁、保持锁的获取顺序、设置超时并回滚、使用死锁检测算法等。Java 1.5引入了java.util.concurrent.locks.Condition接口,可以更好地控制线程的等待和唤醒,减少死锁的...
为了避免死锁,应该尽量避免在同步代码块中嵌套使用同步,确保锁的释放和获取顺序一致。 通过以上内容,可以看出,Java多线程是面试中的一个核心知识点,涉及到的概念和实现方式非常丰富。对于准备Java工程师面试的...
在这个例子中,`MyThread1`类的`run()`方法使用了`synchronized`关键字,锁对象是`lock`。 当线程进入`synchronized`代码块时,它会获取到`lock`对象的锁。如果其他线程已经持有这个锁,当前线程将会被阻塞,直到该...
3. 使用死锁检测算法:Java从1.5版本开始引入了`java.util.concurrent.locks.Condition`,它可以用于检测和避免死锁。此外,JDK 1.6引入了`java.util.concurrent.locks.LockSupport.park()`和`LockSupport.unpark...
Java提供了多种避免死锁的方法,如避免嵌套锁、设置锁的超时、使用tryLock()等。理解死锁的四个必要条件(互斥、占有并等待、无剥夺和循环等待)有助于我们设计更安全的多线程程序。 然后,我们关注Java的wait/...
7. **死锁、活锁和饥饿**:在更复杂的并发场景中,我们还需要关注死锁(两个或更多线程相互等待对方释放资源导致僵持)、活锁(线程不断重试但无法继续执行)和饥饿(线程由于资源分配不公平永远无法执行)等问题,...
避免这些问题需要正确设计线程同步策略,如合理使用锁、避免嵌套锁,以及适时调用 `wait()` 和 `notify()`。 5. **最佳实践** - 使用高级并发工具:Java并发包提供的高级并发工具如 `ExecutorService` 和 `Future`...
在iOS开发中,多线程技术是不可或缺的一部分,它能够帮助我们实现程序的并发执行,提升应用程序的响应速度。线程锁则是确保多线程环境下...在使用线程锁时,一定要注意避免死锁和活锁问题,确保代码的健壮性和效率。
这种特性避免了死锁的发生,使得线程在嵌套调用中可以自由地进入和退出同步块。 5. **公平锁/非公平锁** - **公平锁**按照请求锁的顺序进行分配,保证线程等待的公平性,但可能导致低效率,因为等待时间长的线程...
总结来说,Java中的可重入锁是一种强大的并发控制机制,它确保了在多线程环境中,递归调用和嵌套同步块可以正确地执行,而不会引发死锁。无论是 `synchronized` 还是 `ReentrantLock`,它们都提供了可重入性,为...
- **银行示例**:书中通过银行账户转账的例子详细解释了`wait`和`notify`的使用。 - **`wait()`和`notify()`**:这两个方法用于控制线程之间的同步,`wait()`使当前线程等待,而`notify()`唤醒正在等待的线程。 - **...
在Java并发编程中,Lock接口及其实现类是重要的同步机制,相比传统的synchronized关键字,提供了更细粒度的控制和更高的灵活性。本文将深入探讨JavaLock中的ReentrantLock(可重入锁)以及与其紧密相关的Condition...