【Java】多线程、线程同步、线程通信、线程调度与死锁(3)

电脑杂谈  发布时间:2019-06-22 05:17:01  来源:网络整理

java线程死锁_java多线程死锁_linux 线程死锁

注意:线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,此时并不会释放锁。

多线程资源控制,由于线程之间共享进程中的资源,所以同一进程中的多个线程的通讯的重心之一是对共享的资源进行控制,例如当多个线程同时使用进程某个资源时,有可能需要采用互斥/同步等手段保证资源被正确操作,在采用互斥/同步手段时候,需要避免产生死锁的情况。__detachstate,表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时自 行释放所占用的资源。__detachstate, 表示新线程是否与进程中其他线程脱离同步,如果置位则新线程不能用pthread_join()来同步,且在退出时自行释放所占用的资源。

举个实际例子:有一天,老王和老张在工地里吃饭,恰巧剩下最后一双筷子。老王拿了一根,老张拿了一根(就当这俩有毛病吧)。于是老张在等待老王放弃筷子,那么老王也想让老张先放弃。这时,他们俩就抢了起来啊,然后咔嚓一声,其中一根断了(意味着程序bug),那么这俩货就这样僵持住了,谁也吃不了。

死锁代码:

public class TestDeadlock implements Runnable {
	Zhang zhang = new Zhang();
	Wang wang = new Wang();
	public void init() {
		zhang.waitting(wang);
	}
	public static void main(String[] args) {
		System.out.println("老张、老王各有一根筷子");
		TestDeadlock dl = new TestDeadlock();
		new Thread(dl).start();
		dl.init();
	}
	@Override
	public void run() {
		wang.waitting(zhang);
	}
}
class Zhang {
	public synchronized void waitting(Wang wang) {
		try {
			Thread.currentThread().sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		wang.eat();
	}
	public synchronized void eat() {
		System.out.println("老张想吃饭,等待老王给筷子");
	}
}
class Wang {
	public synchronized void waitting(Zhang zhang) {
		zhang.eat();
	}
	public synchronized void eat() {
		System.out.println("老王想吃饭,等待老张给筷子");
	}
}

死锁的原因就是不同的线程分别占了对方也需要的资源,这时谁也不肯退让,导致程序停止。我们不可能去专门编写死锁,但出现死锁时就要我们去解救。解决方法:专门的算法、原则。或者尽量减少同步资源的定义。

wait()是object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyall()方法)时才能唤醒等待池中的线程。这里即保证了其他线程b对获取到初始化锁的线程a的重排序不可见,即线程a进入类的初始化并将status设置为正在初始化,当线程b进入初始化队列时,会获取到a设置的status并乖乖等待,直到a初始化结束后将status设置为初始化结束释放锁并唤醒其他等待线程,到这里a的初始化过程完成,b才被唤醒并获取锁接着读取status为初始化结束,b直接释放锁,到这里线程b的初始化过程完成。先说一下什么是等待/通知机制,所谓等待/通知机制,就是线程a在执行的时候,需要一个其他线程来提供的结果,但是其他线程还没有告诉他这个结果是什么,于是线程a开始等待,当其他线程计算出结果之后就将结果通知给线程a,a线程唤醒,继续执行。

做法很简单,标记访问某共享资源的那部分代码,当程序运行到有标记的地方时,clr(具体是什么可以先不管,只要知道它能控制就行)对各线程进行调整:如果已有线程在访问一资源,clr就会将其他访问这一资源的线程挂起,直到前一线程结束对该资源的访问。1、当有两个(或以上)线程共同去访问一个object共享对象时,同一时刻只有一个线程可以访问该对象的synchronized(this)同步方法(或同步代码块),也就是说,同一时刻,只能有一个线程能够得到cpu的执行,另一个线程必须等待当前获得cpu执行的线程完成之后才有机会获取该共享对象的锁。2、间接制约关系,即两个线程需要访问同一资源,该资源在同一时刻只能被一个线程访问,这种关系称之为线程间对资源的互斥访问,某种意义上说互斥是一种制约关系更小的同步。

notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待

notifyAll ():唤醒正在排队等待资源的所有线程结束等待

例子:打印整数,实现单双号交替

public class TestThread3 {
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		Thread th1 = new Thread(myThread);
		th1.setName("==单数==");
		th1.start();
		Thread th2 = new Thread(myThread);
		th2.setName("==双数==");
		th2.start();
	}
}
class MyThread implements Runnable {
	int count = 21;
	public void run() {
		while (true) {
			synchronized (this) {
				notify();
				if (count > 0) {
					System.out.println(Thread.currentThread().getName() + count--);
				} else {
					break;
				}
				
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

到此为止,线程的几个内容已经基本讲完了。掌握这些线程的知识点,可以开发出更加高效的软件,多线程编程也是能写出更高效软件的一种手段。

©原文链接:https://blog.csdn.net/smile_Running/article/details/86745128

@作者博客:_Xu2WeI


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-107571-3.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...