下面我们来看看这个demo

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

#include <stdlib.h>

int myglobal;

void * thread_function(void * arg)

{

int i,j;

for (i=0; i<20; i++) {

j=myglobal;

j++;

printf(".");

fflush(stdout);

sleep(1);

myglobal=j;

}

return  NULL;

}

int main(int argc, const char * argv[])

{

pthread_t mythread;

int i;

if (pthread_create(&mythread, NULL, thread_function, NULL)) {

printf("error creating thread");

abort();

}

for (i=0; i<20; i++) {

myglobal++;

printf("o");

fflush(stdout);

sleep(1);

}

if (pthread_join(mythread, NULL)) {

printf("error joining thread");

abort();

}

printf("\nmyglobal equals %d\n",myglobal);

return 0;

}

对于这个问题,我们知道是这个全局变量没有保护的问题,这样导致一个线程的更改覆盖了另外一个线程的改变。
那下面我们就对这个全局变量myglobal加锁。即在myglobal的范围上下加上lock和unlock,具体如下:

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

#include <stdlib.h>

int myglobal;

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

void * thread_function(void * arg)

{

int i,j;

for (i=0; i<20; i++) {

pthread_mutex_lock(&mymutex);

j=myglobal;

j++;

printf(".");

fflush(stdout);

sleep(1);

myglobal=j;

pthread_mutex_unlock(&mymutex);

}

return  NULL;

}

int main(int argc, const char * argv[])

{

pthread_t mythread;

int i;

if (pthread_create(&mythread, NULL, thread_function, NULL)) {

printf("error creating thread");

abort();

}

for (i=0; i<20; i++) {

pthread_mutex_lock(&mymutex);

myglobal++;

pthread_mutex_unlock(&mymutex);

printf("o");

fflush(stdout);

sleep(1);

}

if (pthread_join(mythread, NULL)) {

printf("error joining thread");

abort();

}

printf("\nmyglobal equals %d\n",myglobal);

return 0;

}

对于线程的运行我们一定不要假设哪个会在前面运行哪个会在后面运行,只要线程创建以后我们可以认为他们是同时运行的。

我们看下互斥对象的使用。

首先是初始化

静态初始化给变量赋一个常数

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

另外也可以动态的创建互斥对象,即像使用malloc一样动态分配,在这边我们使用

int pthread_mutex_init(pthread_mutex_t *restrict, const pthread_mutexattr_t *restrict)

第一个参数是要初始化的互斥对象,这个指针已经分配好了一块内存,第二个参数是设定互斥量属性的,为空则为默认属性。

如果使用了pthread_mutex_init初始化了互斥对象,就要用pthread_mutex_destory来销毁,其参数为指向要销毁的互斥量。注意的是这边不会释放用来存储互斥量pthread_mutex_t的内存,也就是我们可以直接再用pthread_mutex_init来重新初始化被销毁的内存。

另外我们要注意的是不管是创建还是销毁,成功的时候返回的都是0.

使用

pthread_mutex_lock接受一个互斥对象的指针作为参数,将其锁定,如果该互斥对象已经锁定,则该调用者进入睡眠状态,如果函数返回,则唤醒当前线程。

pthread_mutex_unlock与上述配合使用,看到名字我们知道这个是解锁。

这里我们要明确的是一定要尽快对已经加锁的互斥对象进行解锁,以提高性能。

另外一定不要对没有加锁的互斥对象进行解锁,这样pthread_mutex_unlock会调用失败。

我们会考虑下一个问题就是,计算机要不停的监测这个互斥量的状态,改变状态之后要立即做出反应,这样是不可取的,因此也就是有了信号量这一说。

通过信号量来使线程进入睡眠状态或者唤醒这个线程。

pthread2的更多相关文章

  1. volatile关键字及编译器指令乱序总结

    本文简单介绍volatile关键字的使用,进而引出编译期间内存乱序的问题,并介绍了有效防止编译器内存乱序所带来的问题的解决方法,文中简单提了下CPU指令乱序的现象,但并没有深入讨论. 以下是我搭建的博 ...

  2. GDB深入研究——20135308芦畅

    GDB深入研究 一.GDB代码调试 (一)GDB调试实例 在终端中编译一个示例C语言小程序,保存到文件 gdb-sample.c 中,用GCC编译之 #include <stdio.h> ...

  3. GDB深入研究

    GDB深入研究 一.GDB代码调试 (一)GDB调试实例 在终端中编译一个示例C语言小程序,保存到文件 gdb-sample.c 中,用GCC编译之 #include <stdio.h> ...

  4. Linux进程间通信与线程间同步详解(全面详细)

    引用:http://community.csdn.net/Expert/TopicView3.asp?id=4374496linux下进程间通信的几种主要手段简介: 1. 管道(Pipe)及有名管道( ...

  5. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

  6. 【转】 Linux下的多线程编程

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/原文链接:http://www.cnblogs.com/gnuhpc/archive/2012/12/07/280 ...

  7. Linux下的多线程编程

    1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的 Unix也支持线程的概念,但是在一个进程(proces ...

  8. pthread_join和pthread_detach的用法(转)

    一:关于join join join是三种同步线程的方式之一.另外两种分别是互斥锁(mutex)和条件变量(condition variable). 调用pthread_join()将阻塞自己,一直到 ...

  9. Linux系统编程@多线程编程(二)

    线程的操作 线程标识 线程的ID表示数据类型:pthread_t (内核中的实现是unsigned long/unsigned int/指向pthread结构的指针(不可移植)几种类型) 1.对两个线 ...

随机推荐

  1. Sublime Text3 配置 Lua5.3.5开发环境

    所需软件 Sublime Text3 Lua5.3.5 配置过程 解压Lua5.3.5包 官方下载的包内是需要makefile安装的(博主Win10下暂为实现),此处提供自动配置完毕的包:Lua5.3 ...

  2. 百度地图JavaScript API获取用户当前经纬度和详细地理位置,反之通过详细地理位置获取当前经纬度

    前言: 前端时间刚好使用了百度地图的js api定位获取用户当前经纬度并获取当前详细位置和通过当前用户详细地理位置换取用户当前经纬度坐标的功能,为了方便下次找起来方便一些自己在这里记录一下,希望也能够 ...

  3. (转)50道JavaScript基础面试题(附答案)

    https://segmentfault.com/a/1190000015288700 1 介绍JavaScript的基本数据类型 Number.String .Boolean .Null.Undef ...

  4. 国内外知名IT科技博客

    国内 1.36氪(www.36kr.com): 目前国内做的最风生水起的科技博客,以介绍国内外互联网创业新闻为主的博客网站,自己建立有36Tree互联网创业融投资社区.36氪的名字源于元素周期 表的第 ...

  5. JS——模拟百度搜索

    注意事项: 1.for循环移除子节点时,其长度是变化的 2.在文档流中,input.img.p等标签与其他标签有3px的距离,利用左浮动,可以消除3px距离 3.背景图片定位时,第一个值是x轴方向的值 ...

  6. html——特殊字符

  7. Tcl之looping

    1 While loop while test body The while command evaluates test as an expression. If test is true, the ...

  8. Fast-RCNN论文翻译

    http://www.dengfanxin.cn/?p=423 原文地址 本文实现了Fast-RCNN主要部分的翻译工作,在SPPnet出来之后,同在微软的R-CNN的作者Ross迅速怼了回去,抛出了 ...

  9. 如何解决Win10预览版一闪而过的disksnapshot.exe进程?

    Win10之家讯上周微软如约向Insider用户推送了Win10预览版10576更新,本次更新修复了之前版本中存在的一些问题,从日常使用的情况来看,对比之前的预览版系统要更稳定了一些,但是还是存在一些 ...

  10. Centos初始化硬盘分区、挂载

    刚刚买了一台服务器,刚买的服务器的数据盘都是需要自己来分区的,下面就记录一下操作. 通过命令fdisk-l查看硬盘信息 可以看到有两块硬盘/dev/vda和/dev/vdb,启动vda是系统盘vdb是 ...