天天看點

線程同步---互斥量mutex

1. 問題引入:開兩個線程同時對一個全局變量10萬次做自加,結果會如何?

#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 < 100000; 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;
}
           
線程同步---互斥量mutex

思考:多執行幾次,結果很神奇吧,那麼為什麼有的時候會出現結果不是20萬呢,其實質原因是加法不是原子操作。加法對應的彙編指令至少分為讀記憶體,算加法,寫記憶體三步,而線程的切換可能發生在任何一步,這就引起當一個線程還沒完成加法,另一個線程在這個不準确的基礎上做了一次加法,結果自然會比正确結果小。而且線程切換的次數越多結果就越不準确,這就需要我們建立一種同步機制來保證資料的可靠性。

2. 互斥量機制:其實質就是加鎖解鎖

nt 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函數中傳回,互斥量呈鎖定狀态;

#include <stdio.h>
#include <string.h>
#include <pthread.h>

unsigned int g_cn = 0;
/*
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 < 100000; 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 ((error = pthread_join (tids[i], NULL)) != 0) {
			fprintf (stderr, "pthread_join: %s\n", strerror (error));
			return -1;
		}

	pthread_mutex_destroy (&g_mtx);
	printf ("g_cn = %u\n", g_cn);
	return 0;
}
           

能保證結果每次都是20萬。

繼續閱讀