您的位置:首页 > 运维架构 > Linux

linux下信号量semaphore的应用

2011-04-24 19:51 246 查看
生产者线程用于往链表里添加节点,数个工作线程从链表取出节点并处理。对于一般的mutex_lock,mutex_unlock方式,如果这一段时间没有工作,那么工作线程将会不停的调用lock,unlock操作。而这样的操作毫无疑义。

在这里系统给我们提供了另外一种同步机制,信号灯,Semaphore。

信号灯其实就是一个计数器,也是一个整数。每一次调用wait操作将会使semaphore值减一,而如果semaphore值已经为0,则wait操作将会阻塞。每一次调用post操作将会使semaphore值加一。将这些操作用到上面的问题中。工作线程每一次调用wait操作,如果此时链表中没有节点,则工作线程将会阻塞,直到链表中有节点。生产者线程在每次往链表中添加节点后调用post操作,信号灯值会加一。这样阻塞的工作线程就会停止阻塞,继续往下执行。

信号灯的类型为sem_t。在声明后必须调用sem_init()。需要传递两个参数,第一个参数就是你之前声明的sem_t变量,第二个必须为0。当你不再需要信号灯时,你必须调用sem_destroy()来释放资源。

等待信号灯的操作为sem_wait()。投递一个信号的操作为sem_wait()。和互斥量一样,等待信号灯也有一个非阻塞的操作,sem_trywait()。该操作在没有信号灯的时候返回EAGAIN。

下面是一个结合了互斥量和信号灯的例子:

#include <malloc.h>

#include <pthread.h>

#include <semaphore.h>

struct job {

/* Link field for linked list. */

struct job* next;

/* Other fields describing work to be done... */

};

/* A linked list of pending jobs. */

struct job* job_queue;

/* A mutex protecting job_queue. */

pthread_mutex_t job_queue_mutex = PTHREAD_MUTEX_INITIALIZER;

/* A semaphore counting the number of jobs in the queue. */

sem_t job_queue_count;

/* Perform one-time initialization of the job queue. */

void initialize_job_queue ()

{

/* The queue is initially empty. */

job_queue = NULL;

/* Initialize the semaphore which counts jobs in the queue. Its

initial value should be zero. */

sem_init (&job_queue_count, 0, 0);

}

/* Process queued jobs until the queue is empty. */

void* thread_function (void* arg)

{

while (1) {

struct job* next_job;

/* Wait on the job queue semaphore. If its value is positive,

indicating that the queue is not empty, decrement the count by

1. If the queue is empty, block until a new job is enqueued. */

sem_wait (&job_queue_count);

/* Lock the mutex on the job queue. */

pthread_mutex_lock (&job_queue_mutex);

/* Because of the semaphore, we know the queue is not empty. Get

the next available job. */

next_job = job_queue;

/* Remove this job from the list. */

job_queue = job_queue->next;

/* Unlock the mutex on the job queue because we’re done with the

queue for now. */

pthread_mutex_unlock (&job_queue_mutex);

/* Carry out the work. */

process_job (next_job);

/* Clean up. */

free (next_job);

}

return NULL;

}

/* Add a new job to the front of the job queue. */

void enqueue_job (/* Pass job-specific data here... */)

{

struct job* new_job;

/* Allocate a new job object. */

new_job = (struct job*) malloc (sizeof (struct job));

/* Set the other fields of the job struct here... */

/* Lock the mutex on the job queue before accessing it. */

pthread_mutex_lock (&job_queue_mutex);

/* Place the new job at the head of the queue. */

new_job->next = job_queue;

job_queue = new_job;

/* Post to the semaphore to indicate that another job is available. If

threads are blocked, waiting on the semaphore, one will become

unblocked so it can process the job. */

sem_post (&job_queue_count);

/* Unlock the job queue mutex. */

pthread_mutex_unlock (&job_queue_mutex);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: