当编写的多线程应用程序,最常见的一个问题是经验丰富的僵局。

我的问题对社区有:

  1. 什么是一个僵局?

  2. 你怎么检测到他们吗?

  3. 你处理他们?

  4. 最后,你如何防止其发生?

有帮助吗?

解决方案

一个 锁定 发生在多个进程尽量接相同的资源在同一时间。

一个过程的输出,并且必须等待其他来完成。

一个 僵局 发生在等待过程中仍然持有另一种资源,首先需求,才能完成。

因此,一个例子:

资源和资源B使用的过程X和Y过程

  • X开始使用A.
  • X和Y尝试启用B
  • Y'胜'和获取B第一
  • 现在需要使用一个
  • 一个被锁定通过X,这是等待Y

最好的方式,以避免僵局是为了避免具有程序越过这种方式。减少需要任何东西锁尽可能多的,你可以.

在数据库中,避免使很多的变化以不同的表中一个单一的交易,避免触发器和开关以乐观/肮脏/nolock读取尽可能多的。

其他提示

让我解释一个真正的世界(不真实)的例子为一僵局,局势从犯罪电影。想象一下,一个刑事持有人质,并对此,缔约方会议还拥有一个人质,谁是一个朋友的犯罪。在这种情况下,犯罪是不会让人质如果警察不会让他的朋友来让我们去。还缔约方会议是不会让朋友的刑事让我们去,除非犯罪释放人质。这是一个永无止境的不值得信任的情况,因为双方都坚持的第一步。

刑事和警察现场

enter image description here

所以简单地说,当两个线程需要两种不同的资源和他们每个人都有锁的资源,其他的需要,这是一个僵局。

另一个高级别的解释的僵局:破碎的心

你是约会一个女孩一天之后一个论点,双方都是心碎彼此并且在等待一个 我-我-对不起-和-我错过了-你 呼叫。在这种情况下,双方希望进行沟通彼此如果并且只有如果他们中的一个接一个 我-我-对不起 呼叫的从其他。因为这既不是每个将要开始的通信和等待一个被动状态,这两个会等其他要开始的通信从而结束了在一僵局的情况。

僵局只会发生在你有两个或两个以上的锁可获得性的同时,他们抓住了在不同的顺序。

方法,以避免具有僵局是:

  • 避免具有锁的(如果可能),
  • 避免具有超过一个锁
  • 总是锁定在相同的顺序。

定义的僵局,首先我会限定的进程。

过程 : 因为我们知道过程是没什么但是 program 在执行。

资源 : 执行一个程序过程需要一些资源。资源类别可以包括存储器、打印机、Cpu,打开文件、磁带驱动器、CD-ROM光盘,等等。

僵局 : 僵局是一个情况或条件,当两个或多个进程持有某些资源,并试图获得更多的资源,它们不能释放资源,直到他们完成有执行。

僵局状况或情况

enter image description here

在上述图有两个过程 P1p2 有两个资源 R1R2.

资源 R1 是分配给处理 P1 和资源 R2 是分配给处理 p2.来完成执行的过程 P1 需资源 R2, ,所以 P1 请求 R2, 但 R2 已经分配给 P2.

在相同的方式处理 P2 来完成它的执行需要 R1, 但 R1 已经分配给 P1.

这两个进程可能不会释放他们的资源,直至和除非他们完成他们的执行。所以两者都在等待另一个的资源,他们将会等待直到永远。因此,这是一个 僵局 条件。

为了僵局的出现,四个条件必须是真实的。

  1. 相互排斥 -每个资源是目前分配给一个过程,或者它是可用的。(两个进程无法 同时控制同样的资源或是在他们的关键 部分)。
  2. 按住并等待 -进程的目前持有资源可以请求新的资源。
  3. 没有抢先占 -一次一个进程拥有资源,不能被带走的另一个进程或核。
  4. 圆形的等待 -每个进程正在等待获得资源,这是举行由另一个进程。

所有这些条件都满足上述图。

一僵局时发生的情况一线是等待着什么,永远不会发生。

通常,这种情况发生时,一线是等待一个互斥或信号,从未公布之前的主人。

它还频频发生的时候你有一种情况涉及两个螺纹和两个锁是这样的:

Thread 1               Thread 2

Lock1->Lock();         Lock2->Lock();
WaitForLock2();        WaitForLock1();   <-- Oops!

你一般探测到它们,因为事情,你希望发生从来没有这样做,或者应用程序挂起完全。

你可以看看这个 美妙的文章, 下部分 僵局.它是在C#但这个想法仍然是相同的其他平台。我在这里引用,为方便阅读

一僵局时会发生两个线程的每一等资源通过举行 其他的,所以既不可以继续进行。最简单的方式说明这个 是有两个锁:

object locker1 = new object();
object locker2 = new object();

new Thread (() => {
                    lock (locker1)
                    {
                      Thread.Sleep (1000);
                      lock (locker2);      // Deadlock
                    }
                  }).Start();
lock (locker2)
{
  Thread.Sleep (1000);
  lock (locker1);                          // Deadlock
}

僵局的一个共同的问题是在多重处理/进程并发水的问题在操作系统。说有两个进程P1和P2两个全球可共享的资源R1,R2和在关键部分资源需要访问

最初,操作系统分配R1至过程P1和R2处理P2。作为这两个进程同时进行,他们可以开始执行他们的代码,但问题出现时,一个过程的命中的关键部分。所以过程R1会等待的过程P2释放R2,反之亦然...因此,他们将等待永远(僵局状况)。

一个小的比喻...

你的母亲(OS),
你(P1),
你的兄弟(P2),
苹果(R1),
刀(R2),
关键的部分(切割的苹果刀).

你妈妈给你的苹果刀给你的兄弟在开始。
两者都是幸福及播放(执行他们的代码)。
有人对你想来切苹果(关键部分)。
你不想得到苹果你的兄弟。
你的兄弟不要给刀给你。
所以你们两个都要等待很长一段很长时间:)

一僵局时发生的还有一个圆形的连锁线或进程的每个持有一个上锁的资源,并试图锁定资源举行的下一个元素。例如,两个线,持有分别锁定锁和B,都是试图获得其他锁。

僵局时发生的两个线程aquire锁,防止他们从进步。最好的方式,以避免他们是认真的发展。许多嵌入式系统,防止他们通过使用一个监督计时器(计时器,其重置系统,只要如果它挂了一段时间)。

一僵局是一个国家的一个系统,其中没有一个单一的进程/螺纹是能够执行行动。正如其他人,一僵局是通常的结果的情况下,每个流程/线希望获得一个锁定的资源已经锁定由另一个(或甚至相同)的过程/螺纹。

有各种方法找到他们并避免他们。一个思考非常困难和/或试图很多东西。然而,处理并行的是众所周知的困难,大多数(如果不是所有的)人们将不能够完全避免的问题。

一些更正式的方法可以是有用的,如果你是认真的处理这类问题。最实际的方法,我所知道的是使用过程中的理论的方法。在这里,你模型的你的系统中的一些过程语言(例如CCS,CSP,ACP,mCRL2,LOTOS)和使用可用的工具(模型)检查的僵局(也许还有一些其他性质)。实例的工具的使用是FDR、mCRL2,CADP和Uppaal.某些勇敢的人甚至可能会证明其系统中的僵局免费的,通过使用纯粹是象征性的方法(定理证明;看Owicki-河畔的格里斯).

然而,这些正式的方法通常需要做一些努力(例如学习基础知识的过程理论)。但我猜这只是一个后果的事实,即这些问题是很难的。

僵局是一个情况发生时,有少量的可用资源,因为它要求通过不同的进程。这意味着当数量的可用资源变得不到它所要求的用户,那么在这段时间的进程会在等待的状况。有时等待增加更多的和没有任何机会检查出的问题lackness的资源,那么这种情况被称为僵局。实际上,僵局的一个主要问题是我们和它只发生在多任务操作系统。僵局不可能发生在单一的任务操作系统,因为所有资源都存在只有为该任务是当前正在运行。.....

上述一些解释都是不错的。希望这可能也有用的:https://ora-data.blogspot.in/2017/04/deadlock-in-oracle.html

在一个数据库,当一届会议(例如奥拉)想要一个资源举行另一届会议(例如数据),但是这届会议(数据),也要有资源举行的第一届会议(ora).可能有超过2次会议还涉及,但一想法将是相同的。实际上,僵局防止某些交易继续工作。例如:假设、ORA数据保持锁定和要求锁B 和库存持有锁B和请求锁A.

谢谢,

僵局时发生的一线是等待其他线完成,反之亦然。

如何避免?
-避免嵌锁
-避免不必要的锁
-使用螺纹join()

你怎么检测到它?
运行这一命令在cmd:

jcmd $PID Thread.print

参考 :geeksforgeeks

一个典型的和非常简单的程序对于理解 僵局 情况:-

public class Lazy {

    private static boolean initialized = false;

    static {
        Thread t = new Thread(new Runnable() {
            public void run() {
                initialized = true;
            }
        });

        t.start();

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

    public static void main(String[] args) {
        System.out.println(initialized);
    }
}

当主线调用懒惰。主要的,它将检查是否类的懒 已经被初始化,并开始初始化类。的 主线,现在设置初始化为虚假的,创建并启动一个背景 线的运行方法设置初始化为真实的,并且等待的背景下线完成。

这一次,类目前正在进行初始化的另一个线程。在这些情况下,当前线,这是该背景线, 等待上课的对象,直到初始化是完整的。不幸的是,螺纹 就是这样做的初始化,主要的线,正在等待的背景 纹完成。因为这两个线程现在正在等待对方, 程序 陷于僵局。

僵局的问题

  • 最早的计算机操作系统,只跑了一个程序 在一段时间
  • 所有的资源的系统可以利用这一个 程序
  • 后来,操作系统跑了多个程序一次, 交他们
  • 程序需要事先指定什么 资源需要,使他们能够避免冲突 与其他程序运行在相同时间
  • 最终一些操作系统动态提供的资源分配
  • 程序可以请求进一步分配的资源 之后他们已经开始运行
  • 这导致了问题的僵局

一定的阻止流程的每个持有资源和 在等待获得资源举行的,由另一种过程中 设定

一种情况下,在其02或多个相互竞争的行动 每个正在等待对其他要完成,&因此既不是永远 做

僵局的表征

  • 相互排斥
  • 保持和等待
  • 没有抢先占
  • 圆形的等待

方法处理的死锁

  • 确保该系统将永远不会输入的僵局状态
  • 允许该系统输入的僵局状态,然后 恢复
  • 忽略的问题,假装死锁永远不会发生 在系统;使用的大多数的操作系统,包括 UNIX

僵局,预防

  • 相互排斥 –不需要共享资源;必须保持nonsharable资源

  • 按住并等待 –必须保证,只要一个过程 请求的资源,它不会举行任何其他资源

  • 没有抢先占 –如果一个过程,是持有一些 资源的另一个请求 资源不能 立即分配给它的,然后所有的资源,目前正在 举行了被释放

  • 圆形的等待 –实施一个总体排序的所有资源 类型,并要求每一个过程要求资源中的一个 增加以枚举

互斥在本质上是一个锁,提供保护的共用资源。在Linux的线互斥的数据类型是pthread_mutex_t.在使用之前,初始化。

获取共享资源,你要锁上的互斥。如果互斥已经上锁,呼吁将块线,直到互斥。在完成访问,以共享资源,你必须解开它们。

总体而言,有几个不成文的基本原则:

  • 获得锁之前,使用共享资源。

  • 保持锁尽可能短的时间尽可能.

  • 释放锁,如果该线返回一个错误。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top