0 0

线程死锁问题5

以下程序为了学习而写
两个线程依次按序打印从1到100,一个只打印奇数,另一个只打印偶数。但是经常发生死锁,请问为什么
public class Test16 implements Runnable{

private int turn;
private int num;
private int sum;
static Integer counter=0;
public Test16(int turn,int num,int sum){
this.turn=turn;
this.num=num;
this.sum=sum;
}
public  synchronized void run() {
while(counter<sum){
while(turn!=counter%num){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

counter++;
System.out.print(counter+" ");
notifyAll();


}

}

public static void main(String[] args){
new Thread(new Test16(0,2,100)).start();
new Thread(new Test16(1,2,100)).start();
}

}
 
2014年5月27日 11:26

5个答案 按时间排序 按投票排序

0 0

采纳的答案

问题在public  synchronized void run() {  相当于 synchronized(this),而 main中
new Thread(new Test16(0,2,100)).start();
new Thread(new Test16(1,2,100)).start();
这样是2个不同的test16对象,因而是2个不同的锁,2个锁都在等待自己的资源(2个线程都停止了),所以不可能被唤醒。其实楼主想锁定的是共享的counter,counter的是static的,属于类对象,所以要在类上加锁才行。
代码修改如下:

public void run() {
		synchronized (Test16.class) {
			while (counter < sum) {
				while (turn != counter % num) {
					try {
						Test16.class.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}

				counter++;
				System.out.println(counter + "   turn : " + turn);
				Test16.class.notifyAll();

			}
		}

	}

2014年5月27日 13:00
0 0

首先回答lz的问题,为什么会死锁。代码稍微改一下:

while (counter < sum) {
            while (turn != counter % num) {
                try {
                    System.out.println(Thread.currentThread().getName() + " is waiting, " +
                    		"count=" + counter + ", turn=" + turn);
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            counter++;
            System.out.print(counter + " ");
            notifyAll();

        }

增加了一条打印语句。
一个可能的输出:
1 Thread-0 is waiting, count=1, turn=0
2 Thread-1 is waiting, count=2, turn=1

看到没,虽然counter改变了,但由于线程1和线程2不是在同一把锁上进行同步,因此counter的改变并没有触发notifyAll

至于如何修改,前面的答案都回答了

2014年5月27日 14:23
0 0

可以先看看notifyAll和wait的javadoc:“This method should only be called by a thread that is the owner of this object's monitor”,你这个程序的问题就是你把线程实例本身当做锁,但多个线程是不同的实例,就不是同一把锁了,所以程序比较混乱,可以通过简单添加一把锁可以解决:

public class Test16 implements Runnable {

    private int    turn;
    private int    num;
    private int    sum;
    static Integer counter = 0;
    static Object  lock    = new Object();

    public Test16(int turn, int num, int sum){
        this.turn = turn;
        this.num = num;
        this.sum = sum;
    }

    public void run() {
        synchronized (lock) {
            while (counter < sum) {
                while (turn != counter % num) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                counter++;
                if (counter <= sum) {
                    System.out.print(counter + " ");
                }
                lock.notifyAll();
            }
        }
    }

    public static void main(String[] args) {
        new Thread(new Test16(0, 3, 100), "A").start();
        new Thread(new Test16(1, 3, 100), "B").start();
        new Thread(new Test16(2, 3, 100), "C").start();
    }

}

2014年5月27日 13:31
0 0

楼主,根本原因是你这里用了两个不同的对象,是不会实现互斥效果的

引用

new Thread(new Test16(0,2,100)).start();
new Thread(new Test16(1,2,100)).start();


这里两个Test16的对象,每个对象都可以进入你synchronized 的run方法。
这了互斥可以用类似生产者消费者李模式这种概念,或者直接使用阻塞队列,开始时队列只存放一个1,两个线程轮流每次在队列里取,取到消费后,将加1的结果再放入队列,此时notifyAll,另一个线程就可以取到数据。当前线程就会阻塞,以此可以实现你要的效果。

2014年5月27日 13:03
0 0


while(turn!=counter%num){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

turn不等于的时候,然后就wait,
线程调用了wait,就会进入休眠状态并且释放锁,直到其他线程调用相同对象的notify或者notifyAll,这个线程才会(notify的话只是有可能会)重新进入执行队列。当这个线程开始执行的时候它会再次接管锁并执行wait后面的内容(接管锁这个动作会等待锁被其他线程释放)。

2014年5月27日 11:57

相关推荐

    DllMain和多线程死锁 问题

    DllMain和多线程死锁问题 DllMain是Windows操作系统中的动态链接库(DLL)入口点,当进程和线程启动和终止时被系统调用,分别进行创建资源和释放资源等操作。在DllMain中创建线程或终止线程时,如果违背了DllMain的...

    解决线程死锁问题的 生产者 消费者程序.rar_linux_linux 线程_生产者_生产者 消费者_生产者消费者

    本资源“解决线程死锁问题的 生产者 消费者程序.rar”显然是针对这一问题提供的一种解决方案,它特别关注了Linux环境下的线程管理。"生产者-消费者"模型是一个经典的并发编程模型,用于演示如何有效地共享有限资源,...

    多线程死锁问题

    本篇文章将深入探讨Java中的死锁问题,并通过提供的代码示例`ProducerConsumer.java`、`TestDeadLock.java`和`Count3Quit.java`来解释如何识别和解决死锁。 首先,我们需要理解死锁的四个必要条件: 1. **互斥**:...

    Java Swing多线程死锁问题解析

    Java Swing多线程死锁问题解析 Java Swing多线程死锁问题解析是Java开发者经常遇到的问题之一。在基于Java Swing进行图形界面开发时,经常会遇到多线程问题。如果在图形界面的同一个线程中进行查询和运算工作,则会...

    线程死锁的例子

    线程死锁是多线程编程中一个严重的问题,它发生在两个或多个线程相互等待对方释放资源,导致它们都无法继续执行。这个概念在计算机科学中尤为重要,因为并发执行是提高系统性能的关键手段,但如果不妥善处理,死锁...

    lookcop 线程死锁检测工具

    总的来说,Lookcop是一款强大的工具,它可以帮助开发者在复杂多线程环境中快速定位和解决线程死锁问题,提升程序的可靠性和性能。了解和掌握如何使用Lookcop,对于优化多线程应用的性能至关重要。

    linux多线程死锁问题分析

    在Linux系统中,多线程编程是常见的并发执行方式,然而如果不小心,它可能会引发一些问题,特别是死锁。死锁是指两个或多个线程在等待对方释放资源,导致它们都无法继续执行的状态。在这个特定的案例中,我们看到12...

    sqlite3.30.1 数据库模块+支持库(彻底解决多线程死锁问题)-易语言

    SQLite3.30.1是SQLite数据库引擎的一个特定版本,专为易语言用户设计,旨在提供一个高效且可靠的多线程数据库解决方案,特别是在处理可能引发死锁问题的并发操作时。SQLite是一个开源、轻量级的嵌入式数据库,常用于...

    多线程死锁

    明白死锁产生的原因,在程序中演示死锁产生并从而实现多线程陈旭解决死锁(deadlock)这一类问题。

    java模拟线程死锁

    线程死锁是 Java 编程中的一种常见的问题,它可以导致程序的崩溃或性能下降。为了避免线程死锁,我们需要在设计线程之间的交互时,遵循一定的规则和原则,例如避免循环等待、使用锁对象和线程通信机制。

    进程线程及死锁

    在操作系统中,死锁是一个重要的问题,因为它可能会导致系统的崩溃。 在实验中,我们使用互斥锁来避免死锁的发生。互斥锁是指一种机制,它可以防止多个进程同时访问同一个共享资源。通过使用互斥锁,我们可以避免...

    DllMain和多线程死锁[归类].pdf

    DllMain 和多线程死锁 DllMain 是可选择的 DLL 入口指针,当进程和线程启动和终止时被系统调用,分别进行创建资源和释放资源等操作。在 DllMain 中创建线程或结束线程时,都特别要注意一个规则,那就是 DllMain 的...

    Linux系统线程死锁实验报告.pdf

    通过分析本篇实验报告的内容,可以了解到线程同步、互斥锁的使用、多线程编程中的死锁问题以及其解决方法。这对于学习和理解多线程并发编程中的同步和互斥机制,以及线程安全编程是非常有价值的。

    QT中sqlite多线程操作4个注意问题

    然而,当在多线程环境中使用SQLite时,需要注意一些关键问题以确保数据的安全性和一致性。以下是四个重要的考虑因素: 1. **线程安全**: SQLite本身并不提供完全的线程安全,这意味着在不同线程中并发访问数据库...

    java多线程死锁预防机制研究

    ### Java多线程死锁预防机制研究 #### 摘要 随着计算机技术的发展和软件系统日益复杂的背景下,多线程编程技术得到了广泛的应用。多线程能够显著提高程序的执行效率,但也随之带来了诸如死锁等问题。死锁是指两个或...

    Java 线程死锁的问题解决办法

    Java 线程死锁的问题解决办法 Java 线程死锁是指两个或两个以上的线程在执行过程中,相互等待对方释放资源,从而造成的僵持状态。在 Java 中,线程死锁的问题解决办法是非常重要的,下面我们将深入探讨 Java 线程...

    线程死锁CPU过高,请求原因分析

    线程死锁是多线程编程中一个严重的问题,它发生在两个或多个线程相互等待对方释放资源,导致它们都无法继续执行。CPU过高通常与过度的计算、无尽循环、死锁、线程竞争状态等问题相关。在Java编程中,WeakHashMap是一...

Global site tag (gtag.js) - Google Analytics