线程同步---互斥量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;
}

思考:多执行几次,结果很神奇吧,那么为什么有的时候会出现结果不是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万。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 16:57:33

线程同步---互斥量mutex的相关文章

linux系统编程:线程同步-互斥量(mutex)

线程同步-互斥量(mutex) 线程同步 多个线程同时访问共享数据时可能会冲突,于是需要实现线程同步. 一个线程冲突的示例 #include <stdio.h> #include <unistd.h> #include <pthread.h> #define Loop 1000000 //全局资然 int counter = 0; void *fun(void *argv) { int i; for (i = 0; i < Loop; i++) { counter

(转)经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

秒杀多线程第七篇 经典线程同步 互斥量Mutex

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数

秒杀多线程第七篇 经典线程同步 互斥量Mutex(续)

java使用Synchronized关键字实现互斥,而同时有Lock支持. 这两个的效果是等同的,Synchronized性能的起伏较大,而lock比较收敛. 为了代码的可读性,Synchronized更建议使用.

线程同步——互斥量

同步的概念 多个线程可以共享内存空间,在程序中不可避免的需要多个线程协作完成某个功能.那么这些线程就可能会使用某个公共的资源.比如说全局变量,某个文件等等.为了不产生冲突,冲突会产生在多个线程的写操作之间,而读操作则很安全.这就需要多个线程之间的同步. 互斥量的原理 互斥量 实现同步的机制很好理解.可以将互斥量想象为锁.只有当一个线程获得该锁时才有权限对共享资源的操作.从而可以理解为该线程对共享资源上了一把锁,其他线程无权操作.在此线程操作完成之后,需要解锁以便其他线程可以获得该锁.可以想的出来

pThread线程(二) 线程同步--互斥量/锁

互斥量(Mutex)是“mutual exclusion”的缩写.互斥量是实现线程同步,和保护同时写共享数据的主要方法. 互斥量对共享数据的保护就像一把锁.在Pthreads中,任何时候仅有一个线程可以锁定互斥量,因此,当多个线程尝试去锁定该互斥量时仅有一个会成功.直到锁定互斥量的线程解锁互斥量后,其他线程才可以去锁定互斥量.线程必须轮着访问受保护数据. 一个拥有互斥量的线程经常用于更新全局变量.确保了多个线程更新同样的变量以安全的方式运行,最终的结果和一个线程处理的结果是相同的.这个更新的变量

[线程同步互斥]互斥量Mutex

互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互斥量Mutex主要将用到四个函数.下面是这些函数的原型和使用说明. 第一个 CreateMutex 函数功能:创建互斥量(注意与事件Event的创建函数对比) 函数原型: HANDLECreateMutex( LPSECURITY_ATTRIBUTESlpMutexAttributes, BOOLbInitialOwner, LPCTSTRlpName

第9章 用内核对象进行线程同步(3)_信号量(semaphore)、互斥量(mutex)

9.5 信号量内核对象(Semaphore) (1)信号量的组成 ①计数器:该内核对象被使用的次数 ②最大资源数量:标识信号量可以控制的最大资源数量(带符号的32位) ③当前资源数量:标识当前可用资源的数量(带符号的32位) (2)信号量的使用规则 ①如果当前资源计数>0,那么信号量处于触发状态,表示有可用资源. ②如果当前资源计数=0,那么信号量处于未触发状态,表示没有可用资源. ③系统绝不会让当前资源计数变为负数: ④当前资源计数绝对不会大于最大资源计数 (3)信号量的用法 (4)相关函数