下面我们来看看这个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. 安卓UI自适应性

    出于安卓的碎片化原因,针对不同屏幕大小,最好是做到以下几点: 1.能用相对布局的就不用绝对布局,尽量使用权重,weight设置,相对布局和线性布局同条件情况下,优先选线性布局 2.在res目录下创建不 ...

  2. 【转】基于linux下的变量声明declare的用法

    转自:http://techcurtman.iteye.com/blog/1249512 declare 功能介绍:声明变量的属性,如果使用declare,后面没有任何参数,那么bash就会主动将所有 ...

  3. Hadoop Hive概念学习系列之hive的脚本执行(二十)

    相当一部分人,容易忽略hive脚本,其实,这在生产环境里,是非常重要的! $ hive -e "show tables" $ hive -e "show tables & ...

  4. Laravel5.1学习笔记12 系统架构4 服务容器

    Service Container 介绍 绑定的用法  绑定实例到接口 上下文绑定 标签 解析 容器事件 #介绍 The Laravel service container is a powerful ...

  5. php中的抽象方法和抽象类

    1.什么是抽象方法?    我们在类里面定义的没有方法提的方法就是抽象方法.所谓的没有方法体指的是,在声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象方法时方 ...

  6. JS——旋转木马

    1.opacity和zIndex的综合运用 2.样式的数组的替换:向右边滑动---删除样式数组第一位并在数组最后添加:向左边滑动---删除样式数组最后一位并在数组前添加 3.开闭原则,只有当回调函数执 ...

  7. C#——枚举格式转换与比较

    定义一个枚举类型: public enum City { 北京, 上海, 广州 } 控制台判断: static void Main(string[] args) { Console.WriteLine ...

  8. [Windows Server 2012] 杰奇CMS安全设置

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:JIEQI ...

  9. Codeforces_732D_(二分贪心)

    D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  10. IOS7升级攻略

    1) Select the main view, set the background color to black (or whatever color you want the status ba ...