Linux多线程之互斥
题目
共要卖票20张,由命令行输入窗口数,由线程模拟窗口。每卖掉一张票,屏幕显示由几号窗口所卖,一并显示剩余票数
思路
由于票数 ticket_cnt 是全局变量,因此每当一个线程将其减一(卖出一张票),并将其显示,应该被封装为一个原子操作。因为线程是并发执行的,可能当前线程将ticket_cnt减1后还没有来得及显示此时的剩余票数ticket_cnt,ticket_cnt已经被另一个线程减一了。此处通过互斥锁实现互斥。
函数原型
创建线程:
NAME
pthread_create - create a new thread SYNOPSIS
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg); Compile and link with -pthread.
回收线程资源,该函数为阻塞函数。
NAME
pthread_join - join with a terminated thread SYNOPSIS
#include <pthread.h> int pthread_join(pthread_t thread, void **retval); Compile and link with -pthread. DESCRIPTION
The pthread_join() function waits for the thread specified
by thread to terminate. If that thread has already termi-
nated, then pthread_join() returns immediately. The thread
specified by thread must be joinable. If retval is not NULL, then pthread_join() copies the exit
status of the target thread (i.e., the value that the tar-
get thread supplied to pthread_exit(3)) into the location
pointed to by *retval. If the target thread was canceled,
then PTHREAD_CANCELED is placed in *retval. If multiple threads simultaneously try to join with the
same thread, the results are undefined. If the thread
calling pthread_join() is canceled, then the target thread
will remain joinable (i.e., it will not be detached). RETURN VALUE
On success, pthread_join() returns 0; on error, it returns
an error number.
解锁开锁
NAME
pthread_mutex_lock
pthread_mutex_unlock - lock and unlock a mutex SYNOPSIS
#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
初始化锁,销毁锁
NAME
pthread_mutex_destroy, pthread_mutex_init - destroy and initialize a mutex SYNOPSIS
#include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
代码
/*************************************************************************
> File Name: ticket.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Mon 25 Aug 2014 07:40:38 PM CST
************************************************************************/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h> int ticket_cnt = 20; /* 共有20张票 */
typedef struct tag
{
int s_id;
pthread_mutex_t *s_p;
}DATA,*pDATA; void* handler(void *arg )
{
int id = ((pDATA)arg)->s_id;
pthread_mutex_t *p_mutex = ((pDATA)arg)-> s_p;
printf("a window on !: %d \n", id);
while(1)
{
pthread_mutex_lock(p_mutex);
if(ticket_cnt == 0)
{
printf("ticket out! \n");
pthread_mutex_unlock(p_mutex);
free((pDATA)arg);
return (void*)0;
}
--ticket_cnt;
sleep(rand()%3 + 1);
printf("window: %d : a ticket sold. left : %d \n", id,ticket_cnt );
pthread_mutex_unlock(p_mutex);
sleep(rand() % 3 + 1); /* 如果不sleep,锁会一直被这个执行完的线程所占据 */ }
} int main(int argc, char *argv[])
{
srand(getpid());
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
int thd_cnt = atoi(argv[1]); /* 从命令行输入卖票窗口数 */
pthread_t *tds = (pthread_t*)calloc(thd_cnt,sizeof(pthread_t));
int index;
for(index = 0; index < thd_cnt; index++ )
{
pDATA p = (pDATA)calloc(1,sizeof(DATA));
p->s_id = index;
p->s_p = &mutex;
pthread_create(tds + index , NULL,handler,(void*)p);
}
printf("joining...\n");
for(index = 0; index < thd_cnt; index++)
{
pthread_join(tds[index],NULL);
}
pthread_mutex_destroy(&mutex);
return 0;
}
编译运行:
[purple@localhost review]$ gcc ticket.c -lpthread
[purple@localhost review]$ ./a.out 5
joining...
a window on !: 2
a window on !: 3
a window on !: 4
a window on !: 1
a window on !: 0
window: 2 : a ticket sold. left : 19
window: 3 : a ticket sold. left : 18
window: 4 : a ticket sold. left : 17
window: 1 : a ticket sold. left : 16
window: 0 : a ticket sold. left : 15
window: 2 : a ticket sold. left : 14
window: 3 : a ticket sold. left : 13
window: 4 : a ticket sold. left : 12
window: 1 : a ticket sold. left : 11
window: 0 : a ticket sold. left : 10
window: 2 : a ticket sold. left : 9
window: 3 : a ticket sold. left : 8
window: 4 : a ticket sold. left : 7
window: 1 : a ticket sold. left : 6
window: 0 : a ticket sold. left : 5
window: 2 : a ticket sold. left : 4
window: 3 : a ticket sold. left : 3
window: 4 : a ticket sold. left : 2
window: 1 : a ticket sold. left : 1
window: 0 : a ticket sold. left : 0
ticket out!
ticket out!
ticket out!
ticket out!
ticket out!
干货
如果有一个整型参数 a 需要在创建线程时将其传递给线程,那么以下两种传值方式,实际上是由区别的。来看代码:
方式1:
void* handler(void *arg)
{
int val=*(int*)arg;
printf("from main: %d\n",val);
pthread_exit((void*)"hello world");
}
int main()
{
pthread_t thd;
int a=12345;
pthread_create(&thd,NULL,handler,(void*)&a);
printf("thd: %x\n",thd);
pthread_join(thd,(void*)&ret);
return 0;
}
方式2:
void* handler(void *arg)
{
int val=(int)arg;
printf("from main: %d\n",val);
pthread_exit((void*)"hello world");
}
int main()
{
pthread_t thd;
int a=12345;
pthread_create(&thd,NULL,handler,(void*)a);
printf("thd: %x\n",thd);
pthread_join(thd,(void*)&ret);
return 0;
}
对于方式1,传给handler的参数是a的地址,如果a的值之后在主线程里会发生变化,那么传给handler的数值a可能就不是原来我们想传的那个了。
而对于方式2,由于是值传递,我们当时想传什么,传到handler中的就一定是什么。
由此可见,虽然方式1节省了存储空间,但是同样也容易发生错误。
Linux多线程之互斥的更多相关文章
- Linux多线程——使用互斥量同步线程
前文再续,书接上一回,在上一篇文章: Linux多线程——使用信号量同步线程中,我们留下了一个如何使用互斥量来进行线程同步的问题,本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两 ...
- Linux多线程--使用互斥量同步线程【转】
本文转载自:http://blog.csdn.net/ljianhui/article/details/10875883 前文再续,书接上一回,在上一篇文章:Linux多线程——使用信号量同步线程中, ...
- Linux多线程--使用信号量同步线程【转】
本文转载自:http://blog.csdn.net/ljianhui/article/details/10813469 信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过 ...
- [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程
一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...
- Linux多线程(三)(同步互斥)
1. 线程的同步与互斥 1.1. 线程的互斥 在Posix Thread中定义了一套专门用于线程互斥的mutex函数.mutex是一种简单的加锁的方法来控制对共享资源的存取,这个互斥锁只有两种状态(上 ...
- Linux多线程服务端编程一些总结
能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...
- linux多线程同步pthread_cond_XXX条件变量的理解
在linux多线程编程中,线程的执行顺序是不可预知的,但是有时候由于某些需求,需要多个线程在启动时按照一定的顺序执行,虽然可以使用一些比较简陋的做法,例如:如果有3个线程 ABC,要求执行顺序是A-- ...
- Linux多线程编程和Linux 2.6下的NPTL
Linux多线程编程和Linux 2.6下的NPTL 在Linux 上,从内核角度而言,基本没有什么线程和进程的区别--大家都是进程.一个进程的多个线程只是多个特殊的进程他们虽然有各自的进程描述结构, ...
- linux多线程编程(转)
原文地址:http://www.cnblogs.com/BiffoLee/archive/2011/11/18/2254540.html 1.Linux“线程” 进程与线程之间是有区别的,不过Linu ...
随机推荐
- 获取 UIWebView中用户所点击的图片URL
在使用 UIWebView 的时候 (通常是阅读类的 App),会有点击图片放大的需求,那么可以通过设置 UIWebViewDelegate 来过滤请求,取出图片的 URL 这个方法的前提是 img ...
- 用Swift重写公司OC项目(Day1)--程序的AppIcon与LaunchImage如何设置
公司之前的APP呢经过了两次重写,都是使用OC由本人独立开发的,不过这些东西我都不好意思说是自己写的,真心的一个字:丑!!! 客观原因来说主要是公司要的特别急,而且注重的是功能而非效果,公司的美工之前 ...
- GNU make 总结 (三)
一.makefile 变量 makefile中的变量名是大小写敏感的,例如”foo”和”Foo”是两个不同的变量.通常情况下,对于一般变量,我们可以使用小写形式,而对于参数变量,采用全大写形式.当我们 ...
- iOS 进阶 第十六天(0419)
0419 任何view默认不支持多点触控,有一个属性设置Multiple Touch,设置为Yes即可支持多点触控 触摸移动一个view,让view也跟着动代码 关于触摸的一些解释: 注意:touch ...
- 用cmd命令合并N个文件
今天早上朋友发我一篇小说(42个TXT文件),让我给他合并为一个文件.我首先想到的是“Copy”命令,它可以复制文件,也可以合并文件. 例如:合并1.txt和2.txt到12.txt(其为ASCII文 ...
- Cocos2dx中利用双向链表实现无限循环滚动层
[Qboy原创] 在Cocos2dX 3.0 中已经实现一些牛逼的滚动层,但是对于有一些需要实现循环滚动的要求确没有实现,笔者在前段时间的一个做了一个游戏,需求是实现在少有的(13个)英雄中进行循环滚 ...
- web 性能忧化(IIS篇)
1. 调整IIS 7应用程序池队列长度 由原来的默认1000改为65535. IIS Manager > ApplicationPools > Advanced Settings 2. ...
- snmp安装配置
只说一下在ubuntu下如何进行基本的配置. ubuntu Server 12.04 apt-get install snmp snmpd 安装完成之后还要安装snmp-mibs-downloader ...
- GCC笔记
The History of GCC 1984年,Richard Stallman发起了自由软件运动,GNU (Gnu's Not Unix)项目应运而生,3年后,最初版的GCC横空出世,成为第一款可 ...
- 【BZOJ】【3676】【APIO2014】回文串
回文自动机/Manacher+SA 这道题可以用Manacher找出本质不同的回文串(令max增大的所有回文串),然后再用SA跑出来有多少相同. 还有一种做法就是回文自动机(Orz Hzwer)的裸题 ...