Synchronizing Threads with POSIX Semaphores
来源:互联网 发布:厦门软件开发公司 编辑:程序博客网 时间:2024/05/16 08:15
Why semaphores?
- Posix semaphores are easy to use
- sem_init
- sem_wait
- sem_post
- sem_getvalue
- sem_destroy
- Exercises 1 2 3
Now it is time to take a look at some code that does something a little unexpected. The program threadadd.c creates two new threads, both of which increment a global variable called count exactly NITER, with NITER = 1,000,000. But the program produces unexpected results.
Exercise 1. Create a directory called posixsem in your class Unix directory. Download in this directory the code threadadd.c and compile it using
gcc threadadd.c -o threadadd -lpthread
Run the executable threadadd and observe the ouput. Try it on both tanner and felix.
Quite unexpected! Since count starts at 0, and both threads increment it NITER times, we should see count equal to 2*NITER at the end of the program. Something fishy is going on here.
Threads can greatly simplify writing elegant and efficient programs. However, there are problems when multiple threads share a common address space, like the variable count in our earlier example.
To understand what might happen, let us analyze this simple piece of code:
THREAD 1 THREAD 2
a = data; b = data;
a++; b--;
data = a; data = b;
Now if this code is executed serially (for instance, THREAD 1 first and then THREAD 2), there are no problems. However threads execute in an arbitrary order, so consider the following situation:
Thread 1
Thread 2
data
a = data;
---
0
a = a+1;
---
0
---
b = data; // 0
0
---
b = b + 1;<>
0
data = a; // 1
---
1
---
data = b; // 1
1
So data could end up +1, 0, -1, and there is NO WAY to know which value! It is completely non-deterministic!
The solution to this is to provide functions that will block a thread if another thread is accessing data that it is using.
Pthreads may use semaphores to achieve this.
Posix semaphores
All POSIX semaphore functions and types are prototyped or defined in semaphore.h. To define a semaphore object, use
sem_t sem_name;
To initialize a semaphore, use sem_init():
int sem_init(sem_t *sem, int pshared, unsigned int value);
- sem points to a semaphore object to initialize
- pshared is a flag indicating whether or not the semaphore should be shared with fork()ed processes. LinuxThreads does not currently support shared semaphores
- value is an initial value to set the semaphore to
Example of use:
sem_init(&sem_name, 0, 10);
To wait on a semaphore, use sem_wait:
int sem_wait(sem_t *sem);
Example of use:
sem_wait(&sem_name);
- If the value of the semaphore is negative, the calling process blocks; one of the blocked processes wakes up when another process calls sem_post.
To increment the value of a semaphore, use sem_post:
int sem_post(sem_t *sem);
Example of use:
sem_post(&sem_name);
- It increments the value of the semaphore and wakes up a blocked process waiting on the semaphore, if any.
To find out the value of a semaphore, use
int sem_getvalue(sem_t *sem, int *valp);
- gets the current value of sem and places it in the location pointed to by valp
Example of use:
int value;
sem_getvalue(&sem_name, &value);
printf("The value of the semaphors is %d/n", value);
To destroy a semaphore, use
int sem_destroy(sem_t *sem);
- destroys the semaphore; no threads should be waiting on the semaphore if its destruction is to succeed.
Example of use:
sem_destroy(&sem_name);
Using semaphores - a short example
Consider the problem we had before and now let us use semaphores:
Declare the semaphore global (outside of any funcion):
sem_t mutex;
Initialize the semaphore in the main function:
sem_init(&mutex, 0, 1);
Thread 1
Thread 2
data
sem_wait (&mutex);
---
0
---
sem_wait (&mutex);
0
a = data;
/* blocked */
0
a = a+1;
/* blocked */
0
data = a;
/* blocked */
1
sem_post (&mutex);
/* blocked */
1
/* blocked */
b = data;
1
/* blocked */
b = b + 1;
1
/* blocked */
data = b;
2
/* blocked */
sem_post (&mutex);
2
[data is fine. The data race is gone.]
Exercise 2.Use the example above as a guide to fix the program threadadd.c, so that the program always produces the expected output (the value 2*NITER).
To compile a program that uses pthreads and posix semaphores, use
gcc -o filename filename.c -lpthread -lrt
Exercise 3. Download this incomplete producer-consumer code in your posixsem directory. Complete the downloaded code to implement a solution to the Producer-Consumer problem using Posix threads and semaphores.
Comment well your code. Compile and run your program and observe the output. Label each line in the output by the identifier for each producer and consumer (P1, P2, P3, C1, C2, C3). The output of your program should be similar to the following:
[P1] Producing A ...
[P1] Producing B ...
------> [C1] Consuming A ...
------> [C1] Consuming B ...
[P2] Producing A ...
[P2] Producing B ...
------> [C2] Consuming A ...
------> [C2] Consuming B ...
[P3] Producing A ...
[P3] Producing B ...
------> [C3] Consuming A ...
------> [C3] Consuming B ...
[P1] Producing C ...
[P1] Producing D ...
------> [C1] Consuming C ...
------> [C1] Consuming D ...
[P2] Producing C ...
[P2] Producing D ...
------> [C2] Consuming C ...
------> [C2] Consuming D ...
[P3] Producing C ...
[P3] Producing D ...
------> [C1] Consuming C ...
[P2] Producing E ...
------> [C2] Consuming D ...
[P3] Producing E ...
------> [C3] Consuming E ...
------> [C3] Consuming E ...
[P1] Producing E ...
------> [C3] Consuming E ...
[P2] Producing F ...
------> [C2] Consuming F ...
[P3] Producing F ...
------> [C1] Consuming F ...
[P1] Producing F ...
------> [C3] Consuming F ...
To compile a program that uses pthreads and posix semaphores, use
gcc -o filename filename.c -lpthread -lrt
- Synchronizing Threads with POSIX Semaphores
- Synchronizing Threads with POSIX Semaphores
- Getting Started with POSIX Threads
- 《Programming with POSIX Threads》笔记
- Synchronizing threads in Java
- Programming With POSIX Threads 读书笔记(一)
- Programming With POSIX Threads 读书笔记(二)
- Programming With POSIX Threads 读书笔记(三)
- Programming With POSIX Threads(POSIX多线程程序设计)
- Synchronizing threads in Android/Java
- Synchronizing Java Threads on a Shared Resource with Multiple Views @ JDJ
- [转帖]Getting Started With POSIX Threads(台湾同胞翻译的)
- Getting Started With POSIX Threads(台湾同胞翻译的)
- POSIX multi-threads programming
- POSIX Threads Programming
- POSIX Threads Programming
- POSIX Threads Programming
- POSIX Threads Programming
- C#学习几个网址
- DB2设置终止符
- C++学习的几个网址
- thread和task
- C++Primer学习笔记第十一章(11/18)泛型算法
- Synchronizing Threads with POSIX Semaphores
- wireshark readme developer
- wireshark gpa_hfinfo analysis
- GNOME Documentation Library
- 如何提高权重
- 设计模式思考-AbstractFactory/FactoryMethod
- 新站怎么样才能更快的提高权重
- Struts源码粗略分析一:准备开发环境
- 除了巴菲特,你应该知道投资大师之————菲利普·卡雷