当多个线程共享相同的内存的时候,需要确保每个线程都看到一致的数据视图。如果每个线程使用的变量都是其他线程不会读取和修改的。那么就不存在一致性问题。同样,如果变量是只读的,多个线程也不会有一致性的问题。但是当一个线程可以修改的变量其他线程也可以读取或者修改的时候。我们就需要对这些线程进行同步,确保它们在访问变量存储内容时不会访问到无效的值。

首先来看一个线程不同步的例子:

typedef struct foo_test{

int count;

int i;

}foo_test;

void mutex_try(foo_test *f){

pthread_t tid;

while (f->i<20){

tid=pthread_self();

f->count+=1;

printf("the thread id is %d,i is %d,count is %d\n",tid,f->i,f->count);

f->i++;

}

pthread_exit((void *)2);

}

int main()

{

foo_test f;

pthread_t tid1,tid2;

void *tret;

f.count=0;

f.i=0;

pthread_create(&tid1,NULL,mutex_try,&f);

pthread_create(&tid2,NULL,mutex_try,&f);

pthread_join(tid1,&tret);

printf("thread 1 exit code %ld\n",(long)tret);

pthread_join(tid2,&tret);

printf("thread 2 exit code %ld\n",(long)tret);

return 0;

}

运行结果:可以看到当thread1的计数为1的时候,count值从1变成了3,正常应该是2.这是因为thread2在 i=0的时候也对count值增加了1, 因此当thread1在i=1访问的时候,count值就变成了3. 在这里两个线程访问了两次i=0. 这就是不同步导致的

为了解决这个问题,在线程中就必须用到锁,同一时间只允许一个线程访问该变量。也就是修改操作是原子操作。这样就不会存在竞争。可以使用pthread的互斥接口来保护数据,确保同一时间只有一个线程访问数据。互斥从本质上就是一把锁,在访问共享资源前对互斥量进行设置(加锁),在访问完成后释放互斥量(解锁)

互斥变量是用pthread_mutex_t数据类型表示的,在使用互斥变量以前,必须首先对它进行初始化,可以把它设置为常量PTHREAD_MUTEX_INITIALIZER(只适用于静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化,如果动态分配互斥量例如通过malloc调用。在释放内存前需要调用pthread_mutex_destroy。

代码修改如下:

typedef struct foo_test{

int count;

pthread_mutex_t f_lock;

int i;

}foo_test;

void mutex_try(foo_test *f){

pthread_t tid;

while (f->i<20){

tid=pthread_self();

pthread_mutex_lock(&f->f_lock);

f->count+=1;

f->i++;

pthread_mutex_unlock(&f->f_lock);

printf("the thread id is %d,i is %d,count is %d\n",tid,f->i,f->count);

//        Sleep(1000);

}

pthread_exit((void *)2);

}

int main()

{

foo_test *f;

pthread_t tid1,tid2;

void *tret;

f=(foo_test *)malloc(sizeof(foo_test));

f->count=0;

f->i=0;

pthread_mutex_init(&f->f_lock,NULL);

pthread_create(&tid1,NULL,mutex_try,f);

pthread_create(&tid2,NULL,mutex_try,f);

pthread_join(tid1,&tret);

printf("thread 1 exit code %ld\n",(long)tret);

pthread_join(tid2,&tret);

printf("thread 2 exit code %ld\n",(long)tret);

return 0;

}

运行结果如下:可以看到两个线程对于变量i的使用没有重复的了。i的增加可以保持原子性。同理count也是一样

linux c编程:线程互斥一的更多相关文章

  1. linux c编程 -- 线程互斥

    #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h& ...

  2. linux系统编程--线程同步

    同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...

  3. Linux系统编程——线程私有数据

    在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...

  4. linux系统编程--线程

    安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...

  5. Linux C多线程编程-线程互斥

    Linux下的多线程编程需要注意的是程序需要包含头文件pthread.h,在生成可执行文件的时候需要链接库libpthread.a或者libpthread.so. 线程创建函数: pthread_cr ...

  6. Linux多任务编程——线程

    线程基础 △ 由于进程的地址空间是私有的,因此在进行上下文切换时,系统开销比较大 △ 在同一个进程中创建的线程共享该进程的地址空间 △ 通常线程值得是共享相同地址空间的多个任务 △ 每个线程的私有这些 ...

  7. Linux多线程编程——线程的创建与退出

    POSIX线程标准:该标准定义了创建和操纵线程的一整套API.在类Unix操作系统(Unix.Linux.Mac OS X等)中,都使用Pthreads作为操作系统的线程.Windows操作系统也有其 ...

  8. Linux系统编程 —线程同步概念

    同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...

  9. linux多线程编程之互斥锁

    多线程并行运行,共享同一种互斥资源时,需要上互斥锁来运行,主要是用到pthread_mutex_lock函数和pthread_mutex_unlock函数对线程进行上锁和解锁 下面是一个例子: #in ...

  10. linux c编程:互斥锁条件变量

    条件变量:等待与信号发送 使用互斥锁虽然可以解决一些资源竞争的问题,但互斥锁只有两种状态(加锁和解锁),这限制了互斥锁的用途. 条件变量(条件锁)也可以解决线程同步和共享资源访问的问题,条件变量是对互 ...

随机推荐

  1. setContentView

    setContentView(R.layout.main)在Android里面,这句话是什么意思? R.layout.main是个布局文件即控件都是如何摆放如何显示的,setContentView就是 ...

  2. USE [EPPM] [dbo].[REFRDEL_CLEANUP]

    USE [EPPM] GO /****** Object: StoredProcedure [dbo].[REFRDEL_CLEANUP] Script Date: 2016/4/2 16:32:29 ...

  3. 10. 修改端口号【从零开始学Spring Boot】

    转载:http://blog.csdn.net/linxingliang/article/details/51637017 spring boot 默认端口是8080,如果想要进行更改的话,只需要修改 ...

  4. modal html

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 扩充STL-编写自己的迭代器

    这里的迭代器能够与STL组件共同工作,是对STL的一种扩充.   自定义迭代器必须提供iterator_traits的五种特性,分别是迭代器类型.元素类型.距离类型.指针类型与reference类型. ...

  6. js 判断是否包含

    1.判断一个数组中是否包含某元素 arr.indexOf(val) > -1 // true 包含 false 不包含 arr.includes(val) // ES7 true 包含 fals ...

  7. java精确除法计算,四舍五入 Java问题通用解决代码

    主要用java.math.BigDecimal工具类实现,想要了解BigDecimal类可以看java api   正式版:        public static Double divide() ...

  8. MongoDB启动及用户名密码设置

    1.服务启动 下载后的安装步骤,请参见mongoDB安装详细教程 启动服务NET START MongoDB 关闭服务NET STOP MongoDB 启动客户端mongo MongoDB shell ...

  9. .net core 2.0小白笔记(一):开发运行环境搭建

    小白一枚,有任何不妥之处敬请指教 这里不讨论什么设计模式,什么架构,什么什么,就是入门,简单的入门,虽然能跨平台,但是这里还是在win的环境下进行,不扯的那么远 其实官网文档写的挺不错的了,就是偶尔有 ...

  10. Android开发之httpclient文件上传实现

    文件上传可能是一个比較耗时的操作,假设为上传操作带上进度提示则能够更好的提高用户体验,最后效果例如以下图: 项目源代码:http://download.csdn.net/detail/shinay/4 ...