Linux下多线程编程的互斥与同步是怎么回事

嵌入式技术

1372人已加入

描述

本文将说明如何使用信号量实现线程之间的互斥与同步。互斥锁只有0,1两中状态,适合于线程对共享资源的独占访问,很多时候每个资源可以同时被有限的线程访问,此时互斥锁将无法满足;条件变量同步也同样存在这种问题。信号量实际是一种非负整型计数器,可以很好的控制线程之间资源访问,互斥锁能实现的功能,信号量同样可以。

信号量控制资源共享主要是PV原语操作, PV原语是对整数计数器信号量sem的操作。一次 P操作使 sem减一,而一次 V操作使sem 加一。进程(或线程)根据信号量的值来判断是否对公共资源具有访问权限。当信号量sem 的值大于等于零时,该进程(或线程)具有公共资源的访问权限;相反,当信号量 sem的值小于零时,该进程(或线程)就将阻塞直到信号量 sem的值大于等于 0 为止。

Linux 实现了POSIX 的无名信号量,主要用于线程间的互斥同步。这里主要介绍几个常见函数。

· sem_init用于创建一个信号量,并能初始化它的值。

· sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在 于若信号量小于零时,sem_wait将会阻塞进程,而 sem_trywait则会立即返回。

· sem_post相当于V操作,它将信号量的值加一同时发出信号唤醒等待的进程。

· sem_getvalue用于得到信号量的值。

· sem_destroy用于删除信号量。

所需头文件 #i nclude

函数原型 int sem_init(sem_t *sem,int pshared,unsigned int value)

sem:信号量

pshared:决定信号量能否在几个进程间共享。由于目前Linux还没有实现进程间共享信号量,所以这个值只能够取0

value:信号量初始化值

函数返回值 成功:0 ,出错:-1

所需头文件 #i nclude

函数原型

int sem_wait(sem_t *sem)

int sem_trywait(sem_t *sem)

int sem_post(sem_t *sem)

int sem_getvalue(sem_t *sem)

int sem_destroy(sem_t *sem)

函数传入值 sem:信号量

函数返回值 成功:0 ,出错:-1

从上面函数来看,实现线程之间同步信号量比互斥锁使用起来相对容易一些,操作简单,容易理解,适用范围广。

下面上一篇的问题用信号量来实现,线程使用部分没变,主要改变了对资源的控制方式:(代码本人亲自编译通过)

view plaincopy to clipboardprint?

01.#i nclude

02.#i nclude

03.#i nclude

04.#i nclude

05.#i nclude

06.#i nclude

07.

08.int g_Flag = 0;

09.sem_t sem_mutex; // 用于互斥

10.sem_t sem_syn; // 用于同步

11.

12.void *thread1( void *arg );

13.void *thread2( void *arg );

14.int main()

15.{

16. pthread_t tid1, tid2;

17. int rc1, rc2;

18.

19. sem_init( &sem_mutex, 0, 1 );

20. sem_init( &sem_syn, 0, 0 );

21. printf( “ Inter main !n” );

22.

23. rc2 = pthread_create( &tid2, NULL, thread2, NULL );

24. if( rc2 != 0 )

25. printf( “ %s, %d n”, __func__, strerror( rc2 ) );

26.

27. rc1 = pthread_create( &tid1, NULL, thread1, &tid2 );

28. if( rc1 != 0 )

29. printf( “ %s, %d n”, __func__, strerror(rc1) );

30. printf( “ Leave main!nn” );

31.

32. sem_wait( &sem_syn ); // 同步等待,阻塞

33. exit( 0 );

34.}

35.

36.void *thread1( void *arg )

37.{

38. pthread_t *ptid = NULL;

39. printf( “ Enter thread1n” );

40. printf( “ thread1 id: %u, g_Flag: %d n”, ( unsigned int )pthread_self(), g_Flag );

41.

42. if( sem_wait( &sem_mutex ) != 0)

43. {

44. perror(“ pthread1 sem_mutexn”);

45. }

46.

47. if( g_Flag == 2 )

48. sem_post( &sem_syn );

49. g_Flag = 1;

50.

51. if( sem_post( &sem_mutex ) != 0)

52. {

53. perror( “pthread1 sem_postn” );

54. }

55. printf( “ thread1 id: %u, g_Flag: %d n”,( unsigned int )pthread_self(), g_Flag );

56. printf( “Leave thread1 nn” );

57.

58. ptid = ( pthread_t *)arg;

59. printf( “ ptid = %u n”, *ptid );

60. pthread_join( *ptid, NULL );

61. pthread_exit(0 );

62.}

63.

64.void *thread2( void *arg )

65.{

66. printf( “ Enter thread2 !n” );

67. printf( “ thread2 id: %u , g_Flag: %d n”, ( unsigned int)pthread_self(), g_Flag );

68.

69. if( sem_wait( &sem_mutex ) != 0 )

70. {

71. perror( “thread2 sem_wait n” );

72. }

73.

74. if( g_Flag == 1 )

75. sem_post( &sem_syn );

76.

77. g_Flag = 2;

78.

79. if( sem_post( &sem_mutex ) != 0)

80. {

81. perror( “ thread2 sem_postn” );

82. }

83. printf( “ thread2 id: %u , g_Flag: %d n”, ( unsigned int )pthread_self(), g_Flag );

84. printf( “Leave thread2 nn” );

85.

86. pthread_exit(0);

87.}

责任编辑:ct

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分