题目

共要卖票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多线程之互斥的更多相关文章

  1. Linux多线程——使用互斥量同步线程

    前文再续,书接上一回,在上一篇文章: Linux多线程——使用信号量同步线程中,我们留下了一个如何使用互斥量来进行线程同步的问题,本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两 ...

  2. Linux多线程--使用互斥量同步线程【转】

    本文转载自:http://blog.csdn.net/ljianhui/article/details/10875883 前文再续,书接上一回,在上一篇文章:Linux多线程——使用信号量同步线程中, ...

  3. Linux多线程--使用信号量同步线程【转】

    本文转载自:http://blog.csdn.net/ljianhui/article/details/10813469 信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过 ...

  4. [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程

    一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...

  5. Linux多线程(三)(同步互斥)

    1. 线程的同步与互斥 1.1. 线程的互斥 在Posix Thread中定义了一套专门用于线程互斥的mutex函数.mutex是一种简单的加锁的方法来控制对共享资源的存取,这个互斥锁只有两种状态(上 ...

  6. Linux多线程服务端编程一些总结

    能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...

  7. linux多线程同步pthread_cond_XXX条件变量的理解

    在linux多线程编程中,线程的执行顺序是不可预知的,但是有时候由于某些需求,需要多个线程在启动时按照一定的顺序执行,虽然可以使用一些比较简陋的做法,例如:如果有3个线程 ABC,要求执行顺序是A-- ...

  8. Linux多线程编程和Linux 2.6下的NPTL

    Linux多线程编程和Linux 2.6下的NPTL 在Linux 上,从内核角度而言,基本没有什么线程和进程的区别--大家都是进程.一个进程的多个线程只是多个特殊的进程他们虽然有各自的进程描述结构, ...

  9. linux多线程编程(转)

    原文地址:http://www.cnblogs.com/BiffoLee/archive/2011/11/18/2254540.html 1.Linux“线程” 进程与线程之间是有区别的,不过Linu ...

随机推荐

  1. Android程序完全退出的三种方法

    很多网友可能发现自己的Android程序有很多Activity,比如说主窗口A,调用了子窗口B,在B中如何关闭整个Android应用程序呢? 这里Android123给大家三种比较简单的方法实现. 首 ...

  2. IOS中 如何去除Tabview里面cell之间的下划线

    可以利用Tabview的separatorStyle属性来设置,选择其中的UITableViewCellSeparatorStyleNone 即可去除cell之间的下划线 self.tableView ...

  3. c++性能测试

    程序分析是以某种语言书写的程序为对象,对其内部的运作流程进行分析.程序分析的目的主要有三点:一是通过程序内部各个模块之间的调用关系,整体上把握程序的运行流程,从而更好地理解程序,从中汲取有价值的内容. ...

  4. DataView usage combind with event and ViewModel From ERP-DEV

    reflesh the selected item in DataView when we use DataView to display a set of data. Generally, we b ...

  5. EF4.1之基础(实现Code First)

    Code First:顾名思义:就是通过代码生成数据库----通过类生成数据库中对应的表: 首先定义两个类(就是建模的过程): public class Order { public int Orde ...

  6. python 通过urllib模块在svn中下载文件

    #_*_coding:utf-8_*_ import urllib def Schedule(a,b,c): ''' a:已经下载的数据块 b:数据块的大小 c:远程文件的大小 ''' per = 1 ...

  7. Leetcode-Construct Binary Tree from inorder and preorder travesal

    Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may assume that ...

  8. 20145103JAVA第一次实验报告

    20145103<Java程序设计>第一次实验报告 实验内容及其步骤 一.命令行下java程序开发 建立一个java文件,然后在命令行中,对程序进行javac编译,就生成了.class文件 ...

  9. 查询sql耗时(运行时间)

    SET STATISTICS TIME ON SELECT * FROM dbo.UserBase SET STATISTICS TIME OFF

  10. bzoj 1270 DP

    w[i,j]代表高度j,第i颗树的时候的最大值 那么w[i,j]:=max(w[i,j+1],w[k,j+heigh])+sum[i,j]: 但是这样枚举是n^3的,我们发现转移的第二个选择w[k,j ...