下面我们来看看这个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. python自动化测试学习笔记-5常用模块

    上一次学习了os模块,sys模块,json模块,random模块,string模块,time模块,hashlib模块,今天继续学习以下的常用模块: 1.datetime模块 2.pymysql模块(3 ...

  2. 卸载Mysql connect 6.9.9

    我们在卸载MySQL的时候,会发现有一个名为“Connector Net X.X.X”(如:Connector Net 6.9.9)软件总是卸载不成功,下面我们来看看解决方法:1. 在C盘的目录下,有 ...

  3. Laravel5.1学习笔记15 数据库1 数据库使用入门

    简介 运行原生SQL查询  监听查询事件 数据库事务 使用多数据库连接 简介 Laravel makes connecting with databases and running queries e ...

  4. 【年终糖果计划】跟风领一波糖果 candy.one 领取教程

    糖果领取网址(较为稳定):https://candy.one/i/1474564 用微信和QQ打开的朋友请复制到其他浏览器打开 糖果领取网址(较为稳定):https://candy.one/i/147 ...

  5. CSS——半透明

    1.opacity:不仅背景半透明,内部其他元素也半透明 2.rgba():只有背景半透明. <!DOCTYPE html> <html lang="en"> ...

  6. servlet的多线程并发问题

    package gz.itcast.e_thread; import java.io.IOException; import javax.servlet.ServletException; impor ...

  7. 从JavaScript的单线程执行说起

    先看一段代码: 1 2 3 4 5 setTimeout(function(){     alert("a"); }, 0); while(1); alert("b&qu ...

  8. 使用码云gitee.com托管代码

    1.新建项目 可以看到团队资源管理器是这样的,已经在本地有存储库,所有更改可以保存本地 2.在码云上新建项目 项目名称必填,其它项根据情况填写 3.复制项目地址关联到本地存储库 填写码云的项目地址,发 ...

  9. 浅谈SOCKS5代理与HTTP代理的应用区别

    [1]什么是SOCKS5协议. SOCKS是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递.SOCKS是"Sockets”的缩写. 当防火墙后的客户端要访问外部的服务器时,就 ...

  10. cstring 转 string

    都通过基本类型来转换即可:CString可以转换为基本类型LPCTSTR,LPCTSTR根据项目编码可以是const char*或者const wchar_t*:string可以用c_str()转换为 ...