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

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

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. 数据结构与算法——优先队列类的C++实现(二叉堆)

    优先队列简单介绍: 操作系统表明上看着是支持多个应用程序同一时候执行.其实是每一个时刻仅仅能有一个进程执行,操作系统会调度不同的进程去执行. 每一个进程都仅仅能执行一个固定的时间,当超过了该时间.操作 ...

  2. PS 如何制作球面化文字效果

    球面化文字效果图....   00newopen-a   00newopen-b     01mew+channel   02ctrl+L   03ctrl+I   04new+wenzi   05R ...

  3. Nginx:subrequest的使用方式

    参考资料<深入理解Nginx> subrequest是由HTTP框架提供的一种分解复杂请求的设计模式. 它可以把原始请求分解为许多子请求,使得诸多请求协同完成一个用户请求,并且每个请求只关 ...

  4. ASP.NET综合管理ERP系统100%源代码+所有开发文档

    该系统开发环境为:VS2010,数据库採用SQL Server,框架为ASP.NET. 源代码包含所有文档说明,代码简单易懂,凝视完整. 提示:假设没有安装水晶报表系统执行会报错,报表安装程序已经打包 ...

  5. UINavigationController改变动画效果

    @interface UINavigationController (CustomTransition) - (void) pushWithCustomAnimation:(UIViewControl ...

  6. .Net、C# 汉字转拼音,简体繁体转换方法

    Visual Studio International Pack 包含一组类库,该类库扩展了.NET Framework对全球化软件开发的支持.使用该类库提供的类,.NET 开发人员可以更方便的创建支 ...

  7. quick-cocos2d-x3.2 scheduler使用注意事项

    近期在使用scheduler时发现例如以下问题 调用: local scheduler = require(cc.PACKAGE_NAME .. ".scheduler") fun ...

  8. 解决H5在微信浏览器或QQ浏览器修改title的问题

    传送门:http://blog.csdn.net/code_for_free/article/details/51195468 如果是Android,使用 document.title = ‘1231 ...

  9. HTML5 2D平台游戏开发#11斜坡物理

    在游戏中会经常遇到斜坡地形,比如众所周知的魂斗罗,角色可以在坡上移动和跳跃: 斜坡在2D游戏中很常见,处理起来也较为棘手.最初我打算用分离轴定律来实现,在建立了一个物理模型之后: 发现上坡时没什么问题 ...

  10. Android学生管理系统

    现在要做这么一个小的demo,可以添加.展示,并且在添加完了之后刷新列表内容. 要点: 在代码中给线性布局添加View 让控件滚动,放到ScrollView中 保存数据就是把数据保存到本地,然后恢复的 ...