15 {

16 int status;

17 int spin;

18

19 /*

20 * Until end_time, increment the counter each second. Instead of

21 * just incrementing the counter, it sleeps for another second

22 * with the mutex locked, to give monitor_thread a reasonable

23 * chance of running.

24 */

25 while (time (NULL) < end_time)

26 {

27  status = pthread_mutex_lock (&mutex);

28  if (status != 0)

29  err_abort (status, 'Lock mutex');

30  for (spin = 0; spin < SPIN; spin++)

31  counter++;

32  status = pthread_mutex_unlock (&mutex);

33  if (status != 0)

34  err_abort (status, 'Unlock mutex');

35  sleep (1);

36 }

37 printf ('Counter is %#lx ', counter);

38 return NULL;

39 }

40

41 /*

42 * Thread start routine to 'monitor' the counter. Every 3

43 * seconds, try to lock the mutex and read the counter. If the

44 * trylock fails, skip this cycle.

45 */

46 void *monitor_thread (void *arg)

47 {

48 int status;

49 int misses = 0;

50

51

52 /*

53 * Loop until end_time, checking the counter every 3 seconds.

54 */

55 while (time (NULL) < end_time)

56 {

57  sleep (3);

58  status = pthread_mutex_trylock (&mutex);

59  if (status != EBUSY)

60  {

61  if (status != 0)

62  err_abort (status, 'Trylock mutex');

63  printf ('Counter is %ld ', counter/SPIN);

64  status = pthread_mutex_unlock (&mutex);

65  if (status != 0)

66  err_abort (status, 'Unlock mutex');

67  } else

68  misses++; /* Count 'misses' on the lock */

69  }

70  printf ('Monitor thread missed update %d times. ', misses);

71 return NULL;

72 }

73

74 int main (int argc, char *argv[])

75 {

76 int status;

77 pthread_t counter_thread_id;

78 pthread_t monitor_thread_id; 79

80 #ifdef sun

81 /*

82 * On Solaris 2.5, threads are not timesliced. To ensure

83 * that our threads can run concurrently, we need to

84 * increase the concurrency level to 2.

85 */

86 DPRINTF (('Setting concurrency level to 2 '));

87 thr_setconcurrency (2);

88 #endif 89

90 end_time = time (NULL) + 60; /* Run for 1 minute */

91 status = pthread_create (

92  &counter_thread_id, NULL, counter_thread, NULL);

93 if (status != 0)

94  err_abort (status, 'Create counter thread');

95 status = pthread_create (

96  &monitor_thread_id, NULL, monitor_thread, NULL);

97 if (status != 0)

98  err_abort (status, 'Create monitor thread');

99 status = pthread_join (counter_thread_id, NULL);

100 if (status != 0)

101  err_abort (status, 'Join counter thread');

102 status = pthread_join (monitor_thread_id, NULL);

103 if (status != 0)

104  err_abort (status, 'Join monitor thread');

105 return 0;

106 }

3.2.3 Using mutexes for atomicity

Invariants, as we saw in Section 3.1, are statements about your program that must always be true. But we also saw that invariants probably aren't always true, and many can't be. To be always true, data composing an invariant must be modified atomically. Yet it is rarely possible to make multiple changes to a program state

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату