多线程编程之互斥

一.互斥量(mutex)

多个线程同时访问共享数据时可能会冲突。比如某个线程把某个全局变量增加1,这个操作在某平台需要三条指令完成:

(1)从内存读变量值到寄存器;

(2)寄存器的值加1;

(3)将寄存器的值写会内存。

假设两个线程在多处理器平台上同时执行这三条指令,则可能导致最后变量只加了1次,而不是2次。

程序如下:

1 #include<stdio.h>

2 #include<pthread.h>

3 #define MAX 5000

4 static int g_count=0;

5 void *thread_run(void *arg)

6 {

7         int val=0;

8         int i=0;

9         for(i=0;i<MAX;++i)

10         {

11                 val=g_count;

12                 printf("pthread id is:%u,count is:%d\n",\

13                         pthread_self(),g_count);

14                 g_count=val+1;

15         }

16         return NULL;

17 }

18 int main()

19 {

20         pthread_t tid1,tid2;

21         pthread_create(&tid1,NULL,thread_run,NULL);

22         pthread_create(&tid2,NULL,thread_run,NULL);

23         pthread_join(tid1,NULL);

24         pthread_join(tid2,NULL);

25         printf("count final val is:%d\n",g_count);

26         return 0;

27 }

运行结果:

创建两个线程,各自把g_count增加5000次,正常情况下g_count的最后结果应该是10000,但是事实上每次运行该程序的结果都不一样,大概是5000多次。

对于多线程的程序,访问冲突的问题很普遍,解决的办法是引入互斥锁,获得锁的线程可以完成“读——修改——写”的操作,然后释放锁给其他线程,没有获得锁的线程只能等待而不能访问共享数据,这样“读——修改——写”三步操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中间被打断。

mutex的相关操作如下:

返回值:成功返回0,失败返回错误号。

pthread_mutex_init函数初始化的mutex可以用pthread_mutex_destroy销毁。如果mutex变量是静态分配的(全局变量或者static变量),也可以用宏定义PTHREAD_MUTEX_INITIALIZER来初始化,相当于用pthread_mutex_init初始化并且参数arr为NULL。mutex的加锁和解锁操作如下:

返回值:成功返回0,失败返回错误号。

一个线程可以调用pthread_mutex_lock获得mutex,如果这时另一个线程已经调用了pthread_mutex_lock获得该mutex,则当前进程需要挂起等待,直到另一个线程调用pthread_mutex_unlock释放mutex,当前线程被唤醒,才能获得该mutex并继续执行。

如果一个线程既想获得锁,又不想挂起等待,可以调用pthread_mutex_trylock,如果mutex已经被另一个线程获得,这个函数会失败返回EBUSY,而不会使线程挂起等待。

程序实现如下:

1 #include<stdio.h>

2 #include<pthread.h>

3 #define MAX 5000

4 pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;

5 static int g_count=0;

6 void *thread_run(void *arg)

7 {

8         int val=0;

9         int i=0;

10         for(i=0;i<MAX;++i)

11         {

12                 pthread_mutex_lock(&lock);

13                 val=g_count;

14                 printf("pthread id is:%u,count is:%d\n",\

15                         pthread_self(),g_count);

16                 g_count=val+1;

17                 pthread_mutex_unlock(&lock);

18         }

19         return NULL;

20 }

21 int main()

22 {

23         pthread_t tid1,tid2;

24         pthread_create(&tid1,NULL,thread_run,NULL);

25         pthread_create(&tid2,NULL,thread_run,NULL);

26         pthread_join(tid1,NULL);

27         pthread_join(tid2,NULL);

28         printf("count final val is:%d\n",g_count);

29         return 0;

30 }

运行结果如下:

时间: 2024-08-10 22:35:41

多线程编程之互斥的相关文章

C++11多线程编程之互斥量

+(UIImage*)createImageFromView:(UIView*)view { //obtain scale CGFloat scale = [UIScreen mainScreen].scale; 开始绘图,下面方法,第一个参数表示区域大小.第二个参数表示是否是非透明的.如果需要显示半透明效果,需要传NO,否则传YES.第三个参数就是屏幕密度了 UIGraphicsBeginImageContextWithOptions(CGSizeMake(view.frame.size.wi

多线程编程之互斥量

最近在看POSIX多线程编程,想把自己看完之后还记得的只言片语记录一下,加深记忆. 如果多个线程对同一个内存区域进行读写操作,可以使用互斥锁保证某个线程对该内存的操作具有原子性. 使用多线程是为了使程序的运行达到并发甚至并行的目的,互斥锁的使用使多个线程在临界区只能一个一个的运行. 临界区是指操作全局内存区域的那一块代码段. 互斥量的初始化: pthread_t mutex = PTHREAD_MUTEX_INITIALIZER;  静态初始化 pthread_mutex_init();动态初始

多线程编程:互斥

多线程共享一个进程的地址空间虽然线程间通信容易进行,但是多线程同时访问共享对象时需要引入同步和互斥机制. 1.线程间的互斥,引入互斥锁的目的是用来保证共享资源数据操作的完整性.互斥锁主要用来保护临界资源,每个邻界资源都由一个互斥锁来保护,任何时刻最多只能有一个线程能访问该资源.线程必须先获得互斥锁才能访问临界资源,访问完临界资源后释放该锁.如果无法获得锁,线程会阻塞知道获得锁为止. 2同步指的是多个任务按照约定的顺序相互配合完成一件事情,   1 #include<stdio.h>   2 #

Linux下多线程编程之互斥锁、条件变量、信号量

1.进程创建 int pthread_create (pthread_t * thread_id, __const pthread_attr_t * __attr, void *(*__start_routine) (void *), void *__restrict __arg); 第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数. 一个实例: void *producer(void *args); pthread_

Linux系统编程@多线程编程

多线程编程 操作系统原理概念 时间片 进程状态 上下文: 对进程来说,就是进程的执行环境,具体就是各个变量和数据,包括所有的寄存器变量.打开的文件.内存信息等. 进程的写时复制:由于一般 fork后面都接着exec,所以,现在的 fork都在用写时复制的技术,顾名思意,就是,数据段,堆,栈,一开始并不复制,由父,子进程共享,并将这些内存设置为只读.直到父,子进程一方尝试写这些区域,则内核才为需要修改的那片内存拷贝副本.这样做可以提高 fork的效率. 线程函数的可重入性:所谓“重入”,常见的情况

转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等.但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage). 一

【C/C++多线程编程之六】pthread互斥量

多线程编程之线程同步互斥量  Pthread是 POSIX threads 的简称,是POSIX的线程标准. Pthread线程同步指多个线程协调地,有序地同步使用共享资源.[C/C++多线程编程之五]pthread线程深入理解中讲述到,多线程共享进程资源,一个线程访问共享资源需要一段完整地时间才能完成其读写操作,如果在这段时间内被其他线程打断,就会产生各种不可预知的错误.协调线程按一定的规则,不受打扰地访问共享资源,保证正确性,这便是线程同步的出发点.        互斥量,是最简单的线程同步

Linux多线程编程-互斥锁

互斥锁 多线程编程中,(多线程编程)可以用互斥锁(也称互斥量)可以用来保护关键代码段,以确保其独占式的访问,这有点像二进制信号量.POSIX互斥锁相关函数主要有以下5个: #include <pthread.h> int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); int pthread_mutex_destroy(pthread_mutex_t *mutex); int p

python多线程编程(2): 使用互斥锁同步线程

上一节的例子中,每个线程互相独立,相互之间没有任何关系.现在假设这样一个例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1.很容易写出这样的代码: # encoding: UTF-8import threadingimport time class MyThread(threading.Thread): def run(self): global num time.sleep(1) num = num+1 msg = self.name+' set