加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 线程互斥行为

发布时间:2020-12-16 10:28:38 所属栏目:百科 来源:网络整理
导读:我正在学习C.我正在编写一个包含多个线程的应用程序;我知道当一个变量在两个或多个线程之间共享时,最好使用互斥锁来锁定/解锁,以避免死锁和变量的不一致.当我想要更改或查看一个变量时,这一点非常清楚. int i = 0; /** Global */static pthread_mutex_t mute
我正在学习C.我正在编写一个包含多个线程的应用程序;我知道当一个变量在两个或多个线程之间共享时,最好使用互斥锁来锁定/解锁,以避免死锁和变量的不一致.当我想要更改或查看一个变量时,这一点非常清楚.

int i = 0; /** Global */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/** Thread 1. */
pthread_mutex_lock(&mutex);
i++;
pthread_mutex_unlock(&mutex);

/** Thread 2. */
pthread_mutex_lock(&mutex);
i++;
pthread_mutex_unlock(&mutex);

我认为这是正确的.变量i在执行结束时包含整数2.
无论如何,在某些情况下,我不知道确切地将两个函数调用放在哪里.

例如,假设您有一个函数obtain(),它返回一个全局变量.我需要从两个线程中调用该函数.我还有另外两个调用函数set()的线程,用一些参数定义;此函数将设置相同的全局变量.在获取/设置var之前需要执行某些操作时,这两个函数是必需的.

/** (0) */
/** Thread 1,or 2,or 3... */
if(obtain() == something) {

    if(obtain() == somethingElse) {
        // Do this,sometimes obtain() and sometimes set(random number) (1)   
    } else {
        // Do that,just obtain(). (2)
    }

} else {
    // Do this and do that (3)
    // If # of thread * 3 > 10,then set(3*10) For example. (4)
}
/** (5) */

我必须锁定的地方,以及我必须解锁的地方?
我认为情况可能更复杂.我将非常感谢一个详尽的答案.

先感谢您.
-Alberto

解决方法

没有任何保护:

操作系统可以随时中断每个线程,并将处理器交给另一个. “Anytime”包括“实际来自同一C命令的两个汇编指令之间”.

现在,假设您的变量在32位处理器中占用64位.这意味着您的变量占用了两个处理器“单词”.为了编写它,处理器需要两个汇编指令.同样适合阅读.如果线程在两者之间中断,则会遇到麻烦.

为了给出一个更清晰的例子,我将使用两个十进制数字的类比来表示两个二进制32位字.因此,假设您在1位处理器中递增两位十进制数.要增加19到20,必须读取19,进行数学运算,然后写入20.要编写20,必须写入2然后写入0(反之亦然).如果你写2,然后在写0之前被中断,那么内存中的数字将是29,远远不是实际上正确的数字.然后另一个线程继续读取错误的数字.

即使你有一个数字,仍然有读取 – 修改 – 写问题Blank Xavier解释.

使用互斥锁:

当线程A锁定互斥锁时,线程A会检查互斥锁变量.如果它是空闲的,则线程A将其写为已采用.它使用原子指令,一个汇编指令来完成它,因此没有“介于两者之间”来中断.然后它继续增加19到20.它仍然可以在错误的29变量值期间被中断,但是没关系,因为现在没有其他人可以访问该变量.当线程B试图锁定互斥锁时,它会检查互斥锁变量,然后执行该操作.所以线程B知道它无法触及变量.然后它调用操作系统,说“我现在放弃处理器”.线程B将重复它,如果它再次获得处理器.然后再次.直到线程A最终得到处理器,完成它正在做的事情,然后解锁互斥锁.

那么,何时锁定?

这么多东西,取决于它.主要是关于应用程序需要正常工作的特定行为顺序.您需要在阅读或写作之前始终锁定以获得保护,然后再解锁.但是“锁定的代码块”可能有许多命令,或者只有一个命令.保持上面解释的舞蹈并考虑应用程序应该如何表现.

还存在性能问题.如果您锁定/解锁每一行代码,就会浪费时间锁定/解锁.如果只围绕大量代码锁定/解锁,那么每个线程将等待很长时间让另一个线程释放互斥锁.

不是真的“永远”

现在,在某些情况下您可以跳过锁定解锁.它们发生在处理一位数(意味着一个处理器字)变量时,并且每个线程要么只读取它,要么只写它,所以读取的值不会决定以后写入什么值.只有当您非常确定自己在做什么时才这样做,并且确实需要提高性能.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读