Concurrency livelock的好例子?

Concurrency livelock的好例子?,concurrency,livelock,Concurrency,Livelock,我理解什么是livelock,但我想知道是否有人有一个很好的基于代码的livelock示例?我所说的基于代码,并不是指“两个人在走廊里试图越过对方”。如果我再读一遍,我的午餐就要吃完了 撇开轻率的评论不谈,已知的一个例子是在试图检测和处理死锁情况的代码中。如果两个线程检测到死锁,并试图为对方“让开”,那么它们将毫无顾忌地陷入一个循环中,总是“让开”,永远无法向前移动 我所说的“让开”是指他们会释放锁,并试图让另一方获得它。我们可以想象两个线程执行此操作的情况(伪代码): 撇开竞争条件不谈,我们这

我理解什么是livelock,但我想知道是否有人有一个很好的基于代码的livelock示例?我所说的基于代码,并不是指“两个人在走廊里试图越过对方”。如果我再读一遍,我的午餐就要吃完了

撇开轻率的评论不谈,已知的一个例子是在试图检测和处理死锁情况的代码中。如果两个线程检测到死锁,并试图为对方“让开”,那么它们将毫无顾忌地陷入一个循环中,总是“让开”,永远无法向前移动

我所说的“让开”是指他们会释放锁,并试图让另一方获得它。我们可以想象两个线程执行此操作的情况(伪代码):

撇开竞争条件不谈,我们这里的情况是,如果两个线程同时进入,那么它们最终将在内部循环中运行而不继续。显然,这是一个简化的例子。一个有效的解决办法是在线程等待的时间量中加入某种随机性


正确的解决办法是始终尊重环境。选择获得锁的顺序并坚持。例如,如果两个线程总是在lock2之前获取lock1,则不存在死锁的可能性。

这里的一个示例可能是使用定时trylok来获取多个锁,如果无法获取所有锁,请退出并重试

boolean tryLockAll(Collection<Lock> locks) {
  boolean grabbedAllLocks = false;
  for(int i=0; i<locks.size(); i++) {
    Lock lock = locks.get(i);
    if(!lock.tryLock(5, TimeUnit.SECONDS)) {
      grabbedAllLocks = false;

      // undo the locks I already took in reverse order
      for(int j=i-1; j >= 0; j--) {
        lock.unlock();
      }
    }
  }
}
boolean tryLockAll(集合锁){
布尔grabbedAllLocks=false;
对于(int i=0;i=0;j--){
lock.unlock();
}
}
}
}
我可以想象这样的代码会有问题,因为有很多线程冲突,等待获得一组锁。但作为一个简单的例子,我不确定这对我来说是否很有说服力

一个真实的(尽管没有确切的代码)示例是两个相互竞争的进程实时锁定,试图纠正SQL server死锁,每个进程使用相同的等待重试算法重试。虽然这是时间上的幸运,但我看到这种情况发生在具有类似性能特征的单独机器上,以响应添加到EMS主题的消息(例如,多次保存单个对象图的更新),并且无法控制锁顺序

在这种情况下,一个好的解决方案是让相互竞争的消费者(通过对不相关对象的工作进行分区,尽可能避免重复处理)

一个不太理想的解决方案(ok,dirty hack)是提前打破计时坏运气(处理中的一种强制差异),或者在死锁后通过使用不同的算法或一些随机因素来打破它。这可能仍然存在问题,因为每个进程的取锁顺序可能都是“粘性”的,并且这需要等待重试中未考虑的最短时间


另一个解决方案(至少对于SQL Server而言)是尝试不同的隔离级别(例如快照)。

下面是一个非常简单的livelock Java示例,其中丈夫和妻子正在尝试喝汤,但他们之间只有一个勺子。配偶双方都太有礼貌了,如果对方还没有吃东西,他们会把勺子递给对方

公共类活锁{
静态类匙{
私人食肆业主;
公共勺子(就餐者d){owner=d;}
公共用餐者getOwner(){return owner;}
公共同步的void setOwner(Diner d){owner=d;}
公共同步的void use(){
System.out.printf(“%s has eat!”,owner.name);
}
}
静态类餐车{
私有字符串名称;
私家侦探;
公共用餐者(字符串n){name=n;isHungry=true;}
公共字符串getName(){return name;}
公共布尔值isHungry(){return isHungry;}
公共用餐(汤匙、用餐者配偶){
while(isHungry){
//没有勺子,所以耐心等待配偶。
如果(spoon.owner!=此){
试试{Thread.sleep(1);}
catch(InterruptedException e){continue;}
继续;
}                       
//如果配偶饿了,坚持把勺子递给他。
if(party.isHungry()){
System.out.printf(
%s:你先吃我亲爱的%s!%n“,
name,party.getName());
勺子。主人(配偶);
继续;
}
//配偶不饿,所以终于吃了
勺子。使用();
isHungry=假;
System.out.printf(
%s:我饱了,亲爱的%s!%n,
name,party.getName());
勺子。主人(配偶);
}
}
}
公共静态void main(字符串[]args){
最终用餐者丈夫=新用餐者(“Bob”);
最终用餐者妻子=新用餐者(“爱丽丝”);
最终勺子s=新勺子(丈夫);
新线程(新Runnable(){
public void run(){丈夫、妻子);}
}).start();
新线程(新Runnable(){
public void run(){layer.eatWith(s,丈夫);}
}).start();
}
}

杰伯恩代码的Python版本:

import threading
import time
lock = threading.Lock()

class Spoon:
    def __init__(self, diner):
        self.owner = diner

    def setOwner(self, diner):
        with lock:
            self.owner = diner

    def use(self):
        with lock:
            "{0} has eaten".format(self.owner)

class Diner:
    def __init__(self, name):
        self.name = name
        self.hungry = True

    def eatsWith(self, spoon, spouse):
        while(self.hungry):
            if self != spoon.owner:
                time.sleep(1) # blocks thread, not process
                continue

            if spouse.hungry:
                print "{0}: you eat first, {1}".format(self.name, spouse.name)
                spoon.setOwner(spouse)
                continue

            # Spouse was not hungry, eat
            spoon.use()
            print "{0}: I'm stuffed, {1}".format(self.name, spouse.name)
            spoon.setOwner(spouse)

def main():
    husband = Diner("Bob")
    wife = Diner("Alice")
    spoon = Spoon(husband)

    t0 = threading.Thread(target=husband.eatsWith, args=(spoon, wife))
    t1 = threading.Thread(target=wife.eatsWith, args=(spoon, husband))
    t0.start()
    t1.start()
    t0.join()
    t1.join()

if __name__ == "__main__":
    main()
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace LiveLockExample
{
    static class Program
    {
        public static void Main(string[] args)
        {
            var husband = new Diner("Bob");
            var wife = new Diner("Alice");

            var s = new Spoon(husband);

            Task.WaitAll(
                Task.Run(() => husband.EatWith(s, wife)),
                Task.Run(() => wife.EatWith(s, husband))
                );
        }

        public class Spoon
        {
            public Spoon(Diner diner)
            {
                Owner = diner;
            }


            public Diner Owner { get; private set; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void SetOwner(Diner d) { Owner = d; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void Use()
            {
                Console.WriteLine("{0} has eaten!", Owner.Name);
            }
        }

        public class Diner
        {
            public Diner(string n)
            {
                Name = n;
                IsHungry = true;
            }

            public string Name { get; private set; }

            private bool IsHungry { get; set; }

            public void EatWith(Spoon spoon, Diner spouse)
            {
                while (IsHungry)
                {
                    // Don't have the spoon, so wait patiently for spouse.
                    if (spoon.Owner != this)
                    {
                        try
                        {
                            Thread.Sleep(1);
                        }
                        catch (ThreadInterruptedException e)
                        {
                        }

                        continue;
                    }

                    // If spouse is hungry, insist upon passing the spoon.
                    if (spouse.IsHungry)
                    {
                        Console.WriteLine("{0}: You eat first my darling {1}!", Name, spouse.Name);
                        spoon.SetOwner(spouse);
                        continue;
                    }

                    // Spouse wasn't hungry, so finally eat
                    spoon.Use();
                    IsHungry = false;
                    Console.WriteLine("{0}: I am stuffed, my darling {1}!", Name, spouse.Name);
                    spoon.SetOwner(spouse);
                }
            }
        }
    }
}

我把两个人在走廊里经过的例子编了起来。当两条线意识到它们的方向是相同的时,它们就会互相回避

public class LiveLock {
    public static void main(String[] args) throws InterruptedException {
        Object left = new Object();
        Object right = new Object();
        Pedestrian one = new Pedestrian(left, right, 0); //one's left is one's left
        Pedestrian two = new Pedestrian(right, left, 1); //one's left is two's right, so have to swap order
        one.setOther(two);
        two.setOther(one);
        one.start();
        two.start();
    }
}

class Pedestrian extends Thread {
    private Object l;
    private Object r;
    private Pedestrian other;
    private Object current;

    Pedestrian (Object left, Object right, int firstDirection) {
        l = left;
        r = right;
        if (firstDirection==0) {
            current = l;
        }
        else {
            current = r;
        }
    }

    void setOther(Pedestrian otherP) {
        other = otherP;
    }

    Object getDirection() {
        return current;
    }

    Object getOppositeDirection() {
        if (current.equals(l)) {
            return r;
        }
        else {
            return l;
        }
    }

    void switchDirection() throws InterruptedException {
        Thread.sleep(100);
        current = getOppositeDirection();
        System.out.println(Thread.currentThread().getName() + " is stepping aside.");
    }

    public void run() {
        while (getDirection().equals(other.getDirection())) {
            try {
                switchDirection();
                Thread.sleep(100);
            } catch (InterruptedException e) {}
        }
    }
} 
杰伯恩代码的C版本:

import threading
import time
lock = threading.Lock()

class Spoon:
    def __init__(self, diner):
        self.owner = diner

    def setOwner(self, diner):
        with lock:
            self.owner = diner

    def use(self):
        with lock:
            "{0} has eaten".format(self.owner)

class Diner:
    def __init__(self, name):
        self.name = name
        self.hungry = True

    def eatsWith(self, spoon, spouse):
        while(self.hungry):
            if self != spoon.owner:
                time.sleep(1) # blocks thread, not process
                continue

            if spouse.hungry:
                print "{0}: you eat first, {1}".format(self.name, spouse.name)
                spoon.setOwner(spouse)
                continue

            # Spouse was not hungry, eat
            spoon.use()
            print "{0}: I'm stuffed, {1}".format(self.name, spouse.name)
            spoon.setOwner(spouse)

def main():
    husband = Diner("Bob")
    wife = Diner("Alice")
    spoon = Spoon(husband)

    t0 = threading.Thread(target=husband.eatsWith, args=(spoon, wife))
    t1 = threading.Thread(target=wife.eatsWith, args=(spoon, husband))
    t0.start()
    t1.start()
    t0.join()
    t1.join()

if __name__ == "__main__":
    main()
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace LiveLockExample
{
    static class Program
    {
        public static void Main(string[] args)
        {
            var husband = new Diner("Bob");
            var wife = new Diner("Alice");

            var s = new Spoon(husband);

            Task.WaitAll(
                Task.Run(() => husband.EatWith(s, wife)),
                Task.Run(() => wife.EatWith(s, husband))
                );
        }

        public class Spoon
        {
            public Spoon(Diner diner)
            {
                Owner = diner;
            }


            public Diner Owner { get; private set; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void SetOwner(Diner d) { Owner = d; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void Use()
            {
                Console.WriteLine("{0} has eaten!", Owner.Name);
            }
        }

        public class Diner
        {
            public Diner(string n)
            {
                Name = n;
                IsHungry = true;
            }

            public string Name { get; private set; }

            private bool IsHungry { get; set; }

            public void EatWith(Spoon spoon, Diner spouse)
            {
                while (IsHungry)
                {
                    // Don't have the spoon, so wait patiently for spouse.
                    if (spoon.Owner != this)
                    {
                        try
                        {
                            Thread.Sleep(1);
                        }
                        catch (ThreadInterruptedException e)
                        {
                        }

                        continue;
                    }

                    // If spouse is hungry, insist upon passing the spoon.
                    if (spouse.IsHungry)
                    {
                        Console.WriteLine("{0}: You eat first my darling {1}!", Name, spouse.Name);
                        spoon.SetOwner(spouse);
                        continue;
                    }

                    // Spouse wasn't hungry, so finally eat
                    spoon.Use();
                    IsHungry = false;
                    Console.WriteLine("{0}: I am stuffed, my darling {1}!", Name, spouse.Name);
                    spoon.SetOwner(spouse);
                }
            }
        }
    }
}

我修改了@jelbourn的答案。 当其中一个注意到另一个饿了,他(她)应该松开勺子,等待另一个通知,这样就会发生活锁

public class LiveLock {
    static class Spoon {
        Diner owner;

        public String getOwnerName() {
            return owner.getName();
        }

        public void setOwner(Diner diner) {
            this.owner = diner;
        }

        public Spoon(Diner diner) {
            this.owner = diner;
        }

        public void use() {
            System.out.println(owner.getName() + " use this spoon and finish eat.");
        }
    }

    static class Diner {
        public Diner(boolean isHungry, String name) {
            this.isHungry = isHungry;
            this.name = name;
        }

        private boolean isHungry;
        private String name;


        public String getName() {
            return name;
        }

        public void eatWith(Diner spouse, Spoon sharedSpoon) {
            try {
                synchronized (sharedSpoon) {
                    while (isHungry) {
                        while (!sharedSpoon.getOwnerName().equals(name)) {
                            sharedSpoon.wait();
                            //System.out.println("sharedSpoon belongs to" + sharedSpoon.getOwnerName())
                        }
                        if (spouse.isHungry) {
                            System.out.println(spouse.getName() + "is hungry,I should give it to him(her).");
                            sharedSpoon.setOwner(spouse);
                            sharedSpoon.notifyAll();
                        } else {
                            sharedSpoon.use();
                            sharedSpoon.setOwner(spouse);
                            isHungry = false;
                        }
                        Thread.sleep(500);
                    }
                }
            } catch (InterruptedException e) {
                System.out.println(name + " is interrupted.");
            }
        }
    }

    public static void main(String[] args) {
        final Diner husband = new Diner(true, "husband");
        final Diner wife = new Diner(true, "wife");
        final Spoon sharedSpoon = new Spoon(wife);

        Thread h = new Thread() {
            @Override
            public void run() {
                husband.eatWith(wife, sharedSpoon);
            }
        };
        h.start();

        Thread w = new Thread() {
            @Override
            public void run() {
                wife.eatWith(husband, sharedSpoon);
            }
        };
        w.start();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        h.interrupt();
        w.interrupt();

        try {
            h.join();
            w.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

因为并没有被标记为已接受答案的答案,所以我尝试创建一个live lock示例

是我在2012年4月写的,目的是学习多线程的各种概念。这个ti
private Integer getMaterial(final Ingredient ingredient) throws Exception{
        :
        container.lock();
        while (!container.getIngredient(quantity)) {
            container.empty.await(1000, TimeUnit.MILLISECONDS);
            //Thread.sleep(500); //For deadlock
        }
        container.unlock();
        :
}
public boolean getIngredient(int n) throws Exception {
    :
    lock();
    if (quantityHeld >= n) {
        TimeUnit.SECONDS.sleep(2);
        quantityHeld -= n;
        unlock();
        return true;
    }
    unlock();
    return false;
}
2016-09-12 21:31:45.065 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:RUNNABLE, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]
2016-09-12 21:31:45.065 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]
WheatPowder Container has 0 only.
2016-09-12 21:31:45.082 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:RUNNABLE]
2016-09-12 21:31:45.082 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]