晚上好!亲爱的,我提前为糟糕的短信道歉。英语不是我的母语。问题是:有代码,我甚至弄清楚了死锁是如何实现的。但如何摆脱困境是个问题。我被告知要么同步捕获,要么顺序调用线程。
我尝试了如下:
- 我从方法中删除监视器,并在类中创建一个静态对象并将其放入监视器中,如果您调用线程,它会工作,但如果您将线程调用到循环中,一切都会崩溃
- 我还试图将函数so bower.bowBack(this(重写为this.bowBack(bower(,这样就不会从1个线程调用2个对象,但仍然值得将其放入循环中,而且我们没有所需的东西
请告诉我你如何解决这个问题?
更新:我很抱歉没有提供信息。我会进步的。根据分配,您需要输出2个流:
- A:G开枪打了我
- A: 我回击
- G: 他开枪打了我
(流1(
G:他开枪打了我(流2(
他就是这么做的。但一旦你把它放进循环中,它就会冻结。如何组织线程的顺序工作?我不知道如何正确地实现它。
package pr1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//package ru.philosophyit;
public class DeadLock {
static class Friend {
private final String name;
private final Lock lock = new ReentrantLock();
public Friend(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void bow(Friend bower) {
boolean Lock_my = false;
boolean Lock_bower = false;
try
{
while(!Lock_my || !Lock_bower)
{
Lock_my = this.lock.tryLock(100, TimeUnit.MILLISECONDS);
Lock_bower = bower.lock.tryLock(100, TimeUnit.MILLISECONDS);
}
System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
System.out.format("%s: стреляю в ответ!n", this.name);
bower.bowBack(this);
this.lock.unlock();
bower.lock.unlock();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
public void bowBack(Friend bower) {
System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
}
}
/**
* Точка входа в программу
*
* @param args аргументы командной строки
*/
public static void main(String[] args) {
Friend alphonse = new Friend("Alphonse");
Friend gaston = new Friend("Gaston");
for (int i = 0; i < 5; i++)
{
new Thread(() -> alphonse.bow(gaston)).start();
new Thread(() -> gaston.bow(alphonse)).start();
}
}
}
我还对一个静态对象进行了同步,循环正常工作,但输出不是顺序的。即可以存在1个流1个流2个流2流1个,而不是1个流。我不明白为什么。
package pr1;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//package ru.philosophyit;
public class DeadLock {
static Object o = new Object();
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void bow(Friend bower) {
//synchronized(getClass())
synchronized(o)
{
System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
System.out.format("%s: стреляю в ответ!n", this.name);
bower.bowBack(this);
}
}
public void bowBack(Friend bower)
{
//synchronized(getClass())
synchronized(o)
{
System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
}
}
}
public static void main(String[] args) {
Friend alphonse = new Friend("Alphonse");
Friend gaston = new Friend("Gaston");
// for (int i = 0; i < 10; i++)
{
new Thread(() -> alphonse.bow(gaston)).start();
new Thread(() -> gaston.bow(alphonse)).start();
}
}
}
结果是2,代码非常合适,线程的工作顺序并不重要,但消息的顺序很重要。但是,当线程增加时,我们需要大量的同步对象,这使方法2变得复杂。他们说你只需要换几行字,一切都会好起来的。3代码是任务本身的原始形式的代码(因此需要更改行的地方(。我知道2个线程处理不同的对象,因此同步无法正常工作(我们在bowBack上进行阻塞,也许值得重写它?(
package pr1;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//package ru.philosophyit;
public class DeadLock {
static Object o = new Object();
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return name;
}
public synchronized void bow(Friend bower) {
{
System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
System.out.format("%s: стреляю в ответ!n", this.name);
bower.bowBack(this);
}
}
public synchronized void bowBack(Friend bower)
{
{
System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
}
}
}
public static void main(String[] args) {
Friend alphonse = new Friend("Alphonse");
Friend gaston = new Friend("Gaston");
for (int i = 0; i < 10; i++)
{
new Thread(() -> alphonse.bow(gaston)).start();
new Thread(() -> gaston.bow(alphonse)).start();
}
}
}
我们能把箭头看作一种资源吗?
import java.util.concurrent.*;
public class Bowmen implements Runnable{
String name;
Bowmen target;
SynchronousQueue<Object> queue = new SynchronousQueue<>();
public Bowmen(String name){
this.name = name;
}
public void shoot(String name, Object o) throws InterruptedException{
System.out.println(this.name + " : " + name + " shot me.");
queue.put(o);
}
public void run(){
try{
Object o = queue.take();
System.out.println(this.name + " : I will shoot " + target.name);
target.shoot(name, o);
} catch(InterruptedException e){
//just finish.
}
}
public void setTarget(Bowmen t){
target = t;
}
public static void main(String[] args) throws Exception{
Bowmen a = new Bowmen("a");
Bowmen b = new Bowmen("b");
a.setTarget(b);
b.setTarget(a);
for(int i = 0; i<5; i++){
new Thread(a).start();
new Thread(b).start();
}
//all the threads are waiting because there is no resource to share yet.
a.shoot( null, new Object() );
}
}
这将产生输出
a:零射我。
a:我会射b
b:一射我。
b:我会射a
。。。
它将以";a:b开枪打了我;但是程序不会完成,因为没有线程从队列中取出,让最后一次调用shoot完成。