1. 竞争与同步
当多个线程同时访问其所共享的进程资源时,需要相互协调,以防止出现数据不一致、不完整的问题;这就叫线程同步。
范例:vie.c
#include <stdio.h>
#include <string.h>
#include <pthread.h>
unsigned int g_cn = 0;
void* thread_proc (void* arg) {
unsigned int i;
for (i = 0; i < 100000000; i++)
++g_cn;
return NULL;
}
int main (void) {
size_t i;
pthread_t tids[2];
int error;
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((error = pthread_create (&tids[i], NULL, thread_proc, NULL)) != 0) {
fprintf (stderr, "pthread_create: %s\n", strerror (error));
return -1;
}
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((error = pthread_join (tids[i], NULL)) != 0) {
fprintf (stderr, "pthread_join: %s\n", strerror (error));
return -1;
}
printf ("g_cn = %u\n", g_cn);
return 0;
}
运行结果并不是 200000000,原因如下:
理想中的原子++:
----------------------+---------------------+------
线程1 | 线程2 | 内存
-----------+----------+----------+----------+------
指 令 | 寄存器 | 指 令 | 寄存器 | g_cn
-----------+----------+----------+----------+------
读内存 | 0 | | | 0
算加法 | 1 | | | 0
写内存 | 1 | | | 1
| | 读内存 | 1 | 1
| | 算加法 | 2 | 2
| | 写内存 | 2 | 2
-----------+----------+----------+----------+------
现实中的非原子++:
----------------------+---------------------+------
线程1 | 线程2 | 内存
-----------+----------+----------+----------+------
指 令 | 寄存器 | 指 令 | 寄存器 | g_cn
-----------+----------+----------+----------+------
读内存 | 0 | | | 0
| | 读内存 | 0 | 0
算加法 | 1 | | | 0
| | 算加法 | 1 | 0
写内存 | 1 | | | 1
| | 写内存 | 1 | 1
-----------+----------+----------+----------+------
2. 互斥量
int pthread_mutex_init (pthread_mutex_t* mutex, const pthread_mutexattr_t* mutexattr);
亦可表示为:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock (pthread_mutex_t* mutex);
int pthread_mutex_unlock (pthread_mutex_t* mutex);
int pthread_mutex_destroy (pthread_mutex_t* mutex);
1) 互斥量被初始化为非锁定状态;
2) 线程 1 调用 pthread_mutex_lock 函数,立即返回,互斥量呈锁定状态;
3) 线程 2 调用 pthread_mutex_lock 函数,阻塞等待;
4) 线程 1 调用 pthread_mutex_unlock 函数,互斥量呈非锁定状态;
5) 线程 2 被唤醒,从 pthread_mutex_lock 函数中返回,互斥量呈锁定状态;
. . .
范例:mutex.c
#include <stdio.h>
#include <string.h>
#include <pthread.h>
unsigned int g_cn = 0;
/* 用这条语句可以替代下面的 pthread_mutex_init 和 ptread_mutex_destroy;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
*/
pthread_mutex_t g_mtx;
void* thread_proc (void* arg) {
unsigned int i;
for (i = 0; i < 100000000; i++) {
pthread_mutex_lock (&g_mtx);
++g_cn;
pthread_mutex_unlock (&g_mtx);
}
return NULL;
}
int main (void) {
size_t i;
pthread_t tids[2];
int error;
pthread_mutex_init (&g_mtx, NULL);
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((error = pthread_create (&tids[i], NULL, thread_proc, NULL)) != 0) {
fprintf (stderr, "pthread_create: %s\n", strerror (error));
return -1;
}
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((err
当多个线程同时访问其所共享的进程资源时,需要相互协调,以防止出现数据不一致、不完整的问题;这就叫线程同步。
范例:vie.c
#include <stdio.h>
#include <string.h>
#include <pthread.h>
unsigned int g_cn = 0;
void* thread_proc (void* arg) {
unsigned int i;
for (i = 0; i < 100000000; i++)
++g_cn;
return NULL;
}
int main (void) {
size_t i;
pthread_t tids[2];
int error;
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((error = pthread_create (&tids[i], NULL, thread_proc, NULL)) != 0) {
fprintf (stderr, "pthread_create: %s\n", strerror (error));
return -1;
}
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((error = pthread_join (tids[i], NULL)) != 0) {
fprintf (stderr, "pthread_join: %s\n", strerror (error));
return -1;
}
printf ("g_cn = %u\n", g_cn);
return 0;
}
运行结果并不是 200000000,原因如下:
理想中的原子++:
----------------------+---------------------+------
线程1 | 线程2 | 内存
-----------+----------+----------+----------+------
指 令 | 寄存器 | 指 令 | 寄存器 | g_cn
-----------+----------+----------+----------+------
读内存 | 0 | | | 0
算加法 | 1 | | | 0
写内存 | 1 | | | 1
| | 读内存 | 1 | 1
| | 算加法 | 2 | 2
| | 写内存 | 2 | 2
-----------+----------+----------+----------+------
现实中的非原子++:
----------------------+---------------------+------
线程1 | 线程2 | 内存
-----------+----------+----------+----------+------
指 令 | 寄存器 | 指 令 | 寄存器 | g_cn
-----------+----------+----------+----------+------
读内存 | 0 | | | 0
| | 读内存 | 0 | 0
算加法 | 1 | | | 0
| | 算加法 | 1 | 0
写内存 | 1 | | | 1
| | 写内存 | 1 | 1
-----------+----------+----------+----------+------
2. 互斥量
int pthread_mutex_init (pthread_mutex_t* mutex, const pthread_mutexattr_t* mutexattr);
亦可表示为:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock (pthread_mutex_t* mutex);
int pthread_mutex_unlock (pthread_mutex_t* mutex);
int pthread_mutex_destroy (pthread_mutex_t* mutex);
1) 互斥量被初始化为非锁定状态;
2) 线程 1 调用 pthread_mutex_lock 函数,立即返回,互斥量呈锁定状态;
3) 线程 2 调用 pthread_mutex_lock 函数,阻塞等待;
4) 线程 1 调用 pthread_mutex_unlock 函数,互斥量呈非锁定状态;
5) 线程 2 被唤醒,从 pthread_mutex_lock 函数中返回,互斥量呈锁定状态;
. . .
范例:mutex.c
#include <stdio.h>
#include <string.h>
#include <pthread.h>
unsigned int g_cn = 0;
/* 用这条语句可以替代下面的 pthread_mutex_init 和 ptread_mutex_destroy;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
*/
pthread_mutex_t g_mtx;
void* thread_proc (void* arg) {
unsigned int i;
for (i = 0; i < 100000000; i++) {
pthread_mutex_lock (&g_mtx);
++g_cn;
pthread_mutex_unlock (&g_mtx);
}
return NULL;
}
int main (void) {
size_t i;
pthread_t tids[2];
int error;
pthread_mutex_init (&g_mtx, NULL);
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((error = pthread_create (&tids[i], NULL, thread_proc, NULL)) != 0) {
fprintf (stderr, "pthread_create: %s\n", strerror (error));
return -1;
}
for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
if ((err