linux 中的线程并发
Thread concurrency in linux
我是SO的初学者,所以如果问题不清楚,请告诉我。
我正在使用两个线程,例如 A 和 B。我有一个全局变量 'p'。
线程 A 正在循环并递增 'p' 的值。同时 B 试图将 'p' 设置为其他值(两者都是两个不同的线程函数)。
如果我使用互斥量进行同步,并且线程 A 在 while 循环中获得互斥量并递增 'p',但它不会释放互斥量。
所以我的问题是,如果线程A不释放互斥量,线程B可以访问变量'p'??
编辑
线程 B 也使用互斥体保护对 'p' 的访问。
如果线程 A 使用 pthread_mutex_lock() 锁,并且没有释放它,那么如果同一个线程 (A) 尝试再次访问锁会发生什么(记住线程 A 在循环时)
例如
while(1)
{
pthread_mutex_lock(&mutex);
p = 10;
}
如果永远不会释放互斥体,这段代码有什么问题吗?
互斥量没有限制,你需要按照使用互斥量的规则编写你的程序。
以下是在共享资源上使用互斥锁的基本步骤:
- 先获取锁
- 做作业(A增加,B设定值)
- 解除锁定,
如果A&B都遵守规则,则B不能修改,A保持锁。
或者,如果您的线程 B 没有先获取锁,它当然可以修改变量,但这将是并发编程的错误。
而且,顺便说一下,你也可以将condition
和mutex
一起使用,这样你就可以让线程等待并互相通知,而不是一直循环,这是一种浪费机器资源。
针对您更新的问题
在linux,在c中,获取mutex锁的方法主要有3种,线程获取不到锁怎么办取决于你用的是什么方法。
int pthread_mutex_lock(pthread_mutex_t * mutex );
如果它已经被另一个线程锁定,那么它会阻塞直到锁被解锁,
int pthread_mutex_trylock(pthread_mutex_t * mutex );
类似于pthread_mutex_lock(),但不会阻塞,而是return错误EBUSY,
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict abs_timeout);
类似于pthread_mutex_lock(),但是在return错误之前会等待超时 ETIMEDOUT,
您仍然可以访问线程 B 中的变量,因为互斥量是一个独立的对象,没有连接到变量。如果您在访问 p
之前从线程 B 调用互斥锁,则线程 B 将等待互斥锁被释放。事实上,线程 A 只会执行一次循环体,因为它会等待互斥量被释放,然后才能再次锁定它。
如果您不解锁互斥锁,那么任何锁定同一个互斥锁的调用都将无限期等待,但该变量将是可写的。
在您的示例中,对变量 p
的访问称为临界区,或者互斥锁定和互斥释放之间的代码部分。
静态初始化互斥量的简单示例
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
static int p = 0;
static pthread_mutex_t locker = PTHREAD_MUTEX_INITIALIZER;
static void *
threadFunc(void *arg)
{
int err;
err = pthread_mutex_lock(&locker);
if (err != 0){
perror("pthread_mutex_lock failed");
exit(1);
}
p++;
err = pthread_mutex_unlock(&locker);
if (err != 0){
perror("pthread_mutex_unlock failed");
exit(1);
}
return NULL;
}
int
main(int argc, char *argv[])
{
pthread_t A, B;
pthread_create(&A, NULL, threadFunc, NULL);
pthread_create(&B, NULL, threadFunc, NULL);
pthread_join(A, NULL);
pthread_join(B, NULL);
printf("p = %d\n", p);
return 0;
}
为简洁起见省略了 main 中的错误检查,但应该使用。如果不释放互斥量程序将永远不会完成,线程 B 将永远不会获得锁。
我是SO的初学者,所以如果问题不清楚,请告诉我。
我正在使用两个线程,例如 A 和 B。我有一个全局变量 'p'。 线程 A 正在循环并递增 'p' 的值。同时 B 试图将 'p' 设置为其他值(两者都是两个不同的线程函数)。
如果我使用互斥量进行同步,并且线程 A 在 while 循环中获得互斥量并递增 'p',但它不会释放互斥量。 所以我的问题是,如果线程A不释放互斥量,线程B可以访问变量'p'??
编辑 线程 B 也使用互斥体保护对 'p' 的访问。
如果线程 A 使用 pthread_mutex_lock() 锁,并且没有释放它,那么如果同一个线程 (A) 尝试再次访问锁会发生什么(记住线程 A 在循环时) 例如
while(1)
{
pthread_mutex_lock(&mutex);
p = 10;
}
如果永远不会释放互斥体,这段代码有什么问题吗?
互斥量没有限制,你需要按照使用互斥量的规则编写你的程序。
以下是在共享资源上使用互斥锁的基本步骤:
- 先获取锁
- 做作业(A增加,B设定值)
- 解除锁定,
如果A&B都遵守规则,则B不能修改,A保持锁。
或者,如果您的线程 B 没有先获取锁,它当然可以修改变量,但这将是并发编程的错误。
而且,顺便说一下,你也可以将condition
和mutex
一起使用,这样你就可以让线程等待并互相通知,而不是一直循环,这是一种浪费机器资源。
针对您更新的问题
在linux,在c中,获取mutex锁的方法主要有3种,线程获取不到锁怎么办取决于你用的是什么方法。
int pthread_mutex_lock(pthread_mutex_t * mutex );
如果它已经被另一个线程锁定,那么它会阻塞直到锁被解锁,
int pthread_mutex_trylock(pthread_mutex_t * mutex );
类似于pthread_mutex_lock(),但不会阻塞,而是return错误EBUSY,
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict abs_timeout);
类似于pthread_mutex_lock(),但是在return错误之前会等待超时 ETIMEDOUT,
您仍然可以访问线程 B 中的变量,因为互斥量是一个独立的对象,没有连接到变量。如果您在访问 p
之前从线程 B 调用互斥锁,则线程 B 将等待互斥锁被释放。事实上,线程 A 只会执行一次循环体,因为它会等待互斥量被释放,然后才能再次锁定它。
如果您不解锁互斥锁,那么任何锁定同一个互斥锁的调用都将无限期等待,但该变量将是可写的。
在您的示例中,对变量 p
的访问称为临界区,或者互斥锁定和互斥释放之间的代码部分。
静态初始化互斥量的简单示例
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
static int p = 0;
static pthread_mutex_t locker = PTHREAD_MUTEX_INITIALIZER;
static void *
threadFunc(void *arg)
{
int err;
err = pthread_mutex_lock(&locker);
if (err != 0){
perror("pthread_mutex_lock failed");
exit(1);
}
p++;
err = pthread_mutex_unlock(&locker);
if (err != 0){
perror("pthread_mutex_unlock failed");
exit(1);
}
return NULL;
}
int
main(int argc, char *argv[])
{
pthread_t A, B;
pthread_create(&A, NULL, threadFunc, NULL);
pthread_create(&B, NULL, threadFunc, NULL);
pthread_join(A, NULL);
pthread_join(B, NULL);
printf("p = %d\n", p);
return 0;
}
为简洁起见省略了 main 中的错误检查,但应该使用。如果不释放互斥量程序将永远不会完成,线程 B 将永远不会获得锁。