2012-07-12 47 views
3

什么时候应该在多线程编程中使用“锁定”?只需锁定每个线程将修改的区域或锁定每个线程可以访问的区域,即使它不会被修改?什么时候应该在多线程编程中使用“锁定”?

struct share_data { 
    /* share data */ 
    thread_id; 
} 

thread 1 will exceute main() function: 
    Initial share data. /* need lock */ 

    join all thread(share_data.thread_id, &status) /* access share data thread_id, lock or not? */ 
    exit. 

other threads will: 
    access share_data, /* lock or not? */ 
    modify share_data, /* lock */ 
    exit. 

感谢您的关注,如果你有更多的时间,关于真正的代码的更多详细信息:

/* 
the number of threads will be input by user. Structure "tdata" and "tlist" stores 
information of each thread, including: "tid" - thread id which is gaven by 1st argument 
of pthread_create(), "torder" which is the order of calling pthread_create() for each 
thead, "status" stores work status of each thread. I allocate memory for "tlist" 
dynamically. Now, we assume that the number of threads is NUM_THREADS(5). I do not use 
the 4th argument to pass data to each thread, I use global variable "tdata", "tlist" as 
shared data to them. "mutex" variable is used to make sure those threads share data safely, 
but it seems not works correctly. 

I wanna each thread can get "torder", and maybe modify the status before calling 
pthread_exit(). 
*/ 
#include <pthread.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 

/* #define NUM_THREADS 5 */ 
struct tdata { 
     pthread_t tid; 
     int torder; 
     int status; 
     struct tdata *next; 
}; 
typedef struct tdata tdata_t; 
struct tdatalist { 
     tdata_t *head; 
     tdata_t *tail; 
}tlist; 

pthread_mutex_t mutex; 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
void *tfunc() { 
     tdata_t *p, *q; 
     unsigned long int tid; 
     int torder; 

     p = tlist.head; 
     q = NULL; 
     pthread_mutex_lock(&mutex); 

     tid = pthread_self(); 

     while (p->tid!=tid && p->next!=NULL) { 
       q = p; 
       p = p->next; 
     } 
     tid = p->tid; 
     torder = p->torder; 
     /* p->status = 0; */ 
     pthread_mutex_unlock(&mutex); 
     /* printf ("I am thread %lu, myorder %d, thread_exit.\n", tid, torder); */ 
     printf ("I am thread %0x, myorder %d, thread_exit.\n", tid, torder); 

     pthread_exit((void *)torder); 
} 

int main (int argc, char *argv[]) { 
/*  pthread_t thread[NUM_THREADS]; */ 

     pthread_attr_t attr; 
     int t; 
     tdata_t *tdata_p; 
     int num_threads; 
     printf ("Input number of threads:"); 
     scanf ("%d", &num_threads); 
     printf ("\n"); 

     printf ("Main thread id: %08x\n", pthread_self()); 

     pthread_mutex_init(&mutex, NULL); 
     pthread_attr_init(&attr); 
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 

     tlist.head=tlist.tail=NULL;  /* create and initial tlist */ 
     for (t=0; t<num_threads; t++) { 

       pthread_mutex_lock(&mutex); 
       tdata_p = (tdata_t *) malloc (sizeof (tdata_t)); 
       pthread_create (&tdata_p->tid, &attr, tfunc, NULL); 
       /* tdata_p->tid = thread[t]; */ 
       tdata_p->torder = t; 
       tdata_p->status = 1;   /* for 0,finished the work. for 1,not*/ 
       tdata_p->next = NULL; 

       if(tlist.head == NULL) { 
         tlist.head = tlist.tail = tdata_p; 
       } 
       else { 
         tlist.tail->next = tdata_p; 
         tlist.tail = tdata_p; 
       } 
       pthread_mutex_unlock(&mutex); 

     } 

     /* Join child threads */ 
     pthread_attr_destroy(&attr); 
     pthread_mutex_lock (&mutex); 
     tdata_t *p; 
     tdata_t *q; 
     void *status; 
     p = tlist.head; 
     while (p != NULL) { 
       q = p->next; 
       pthread_join(p->tid, &status); 
       p = q; 
     } 

     pthread_mutex_unlock (&mutex); 

     pthread_mutex_destroy(&mutex); 
     /* delete the list */ 
     p = tlist.head; 
     while (p != NULL) { 
       q = p->next; 
       free (p); 
       p = q; 
     } 
     tlist.head = tlist.tail = NULL; 

     printf ("Main exit.\n"); 
     pthread_exit(NULL); 

     return 0; 
} 
+0

您需要锁定共享数据的* all *读/写访问权限。 – 2012-07-12 02:10:30

+0

一般来说,只要需要访问可变数据,就应该锁定,并且要确保在访问或修改数据时不会有其他线程访问或修改数据。在实践中,这意味着,一旦你锁定了一个关键的代码区域,任何其他线程进入相同的关键区域(即访问相同的数据)必须等到你释放你的锁定,然后才能进入关键区域或访问相同的数据。换句话说,访问share_data:lock;修改share_data:lock; https://www.google.com/#q=posix+lock+tutorial – 2012-07-12 02:12:35

回答

3

任何时候你要读取或写入数据时,需要将其锁定。这可以防止数据尝试读取尚未完成的数据。

另一种说法是,线程或进程之间共享的任何数据在更改或读取之前都应该锁定。

+0

但是当我使用pthread连接线程时,pthread_join()的第一个参数存储在共享数据结构中。如果我锁定了pthread_join(),会发生死锁,因为在主线程中调用的pthread_join()将暂停等待线程终止,并且线程可能会等待主线程主机锁定。我应该怎么做? – 2012-07-12 02:24:15

+0

调用pthread_join时,您不必担心死锁。 pthread_join只能由终止线程调用,这意味着在调用pthread_close时,其他线程所依赖的来自main的所有数据应该已被写入,并且锁定已被删除。如果你曾经给过你正在加入的线程等待变量的话,那么你正在存储你正在存储的结果,以确保发生死锁。如果您需要通过检查该值来检查另一个线程是否正在等待线程,那么您应该使用条件语句。 – retrohacker 2012-07-12 12:16:46

+0

我明白为什么在写入数据时需要对共享数据使用锁,但我不明白为什么需要锁定读取。在读取期间,如果两个线程同时访问相同的数据,则不会更改数据。在这种情况下锁不是不必要的,因为数据没有发生变化? – 2014-08-29 18:38:42

0

除了生产者 - 消费者队列之类的高级线程间通信的短期锁之外,我还会回答“很少有可以避开”的答案。锁会产生死锁,死锁的机会以超线性方式乘以更多的锁。

另外,应用程序中很多pthread_join()调用为0. < 0是不可能的,1或更多的太多。

+0

如何在不调用pthread_join()的情况下等待主线程中的其他线程? – 2012-07-12 10:21:51

+2

锁不会产生死锁,不正确地使用锁和争用条件会产生死锁。不使用锁会导致分段错误,并可能使调试成为一场噩梦。只要你共享了多于一个线程将访问的内存,它就需要被锁定。如果您希望自己的代码能够维护,那么在后续添加代码时锁定所有共享内存是一个不错的主意,您已经受到保护,不会受到竞争条件的影响,也不必担心通过你的旧代码找到你需要锁定和解锁的地方。 – retrohacker 2012-07-12 13:04:08

+0

重点是'加入所有线程(share_data.thread_id,&status)/ *访问共享数据thread_id,是否锁定? * /'访问“share_data.thread_id”,我不能像这样锁定代码'pthread_mutex_lock(&mutex);在pthread_join(share_data。thread_id,&status); pthread_mutex_unlock(&mutex)' – 2012-07-12 14:07:51

相关问题