#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#define FALSE 0
#define TRUE 1
static int shareddata = 50;
struct qnode* tail;
struct qnode q;
pthread_key_t myPred;
typedef struct qnode
{
int locked;
}QNode;
{
int t_id;
QNode qnode;
QNode* myNode;
QNode* myPred;
typedef struct thread
{
pthread_t t;
Arg arg;
}Thread;
QNode* getAndSet(QNode* qnode)
{
pthread_mutex_lock(&mutex);
QNode* pred = tail;
tail = qnode;
pthread_mutex_unlock(&mutex);
return pred;
}
int isLock()
{
int ret;
QNode* qnode = (QNode*)pthread_getspecific(myPred);
if (qnode == NULL)
return FALSE;
return (qnode->locked)?TRUE:FALSE;
}
void lock()
{
/*得到线程的私有变量。*/
QNode* qnode = (QNode*)pthread_getspecific(myNode);
qnode->locked = TRUE;
QNode* pred = getAndSet(qnode);
pthread_setspecific(myPred, pred);
while(pred->locked)
{
}
}
void unlock()
{
QNode* qnode = (QNode*)pthread_getspecific(myNode);
qnode->locked = FALSE;
QNode* pred = (QNode*)pthread_getspecific(myPred);
pthread_setspecific(myNode, pred);
}
void initCLHlock()
{
q.locked = FALSE;
tail = &q;
}
void initThread(Thread* t, int i)
{
t->arg.qnode.locked = TRUE;
t->arg.myNode = &(t->arg.qnode);
t->arg.myPred = NULL;
t->arg.t_id = i;
}
void* run(Arg* t_arg)
pthread_setspecific(myPred, t_arg->myPred);
while (1)
{
/*lock*/
lock();
if (shareddata > 0)
{
printf("%d get %dth ticket\n", t_arg->t_id, shareddata);
if (isLock())
printf("locked!\n");
shareddata--;
/*unlock*/
unlock();
}
else
{
/*unlock*/
unlock();
break;
}
}
}
void main()
{
clock_t start, end;
Thread t[10];
initCLHlock();
pthread_key_create(&myNode, NULL);
pthread_key_create(&myPred, NULL);
int i;
for (i=0; i<4; i++)
{
initThread(&t[i], i);
}
/*start*/
start = clock();
for (i=0; i<4; i++)
if (ret != 0)
{
printf("creat_thread error!\n");
exit(0);
}
}
/*join*/
for (i=0; i<4; i++)
{
pthread_join(t[i].t, NULL);
}
end = clock();
printf("shareddata:%d\n", shareddata);
printf("speed %f seconds\n", (double)(end-start)/CLOCKS_PER_SEC);
}
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#define FALSE 0
#define TRUE 1
static int shareddata = 50;
struct qnode* tail;
struct qnode q;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/*相当于Java的ThreadLocal*/
pthread_key_t myPred;
typedef struct qnode
{
int locked;
}QNode;
/*线程的参数*/
{
int t_id;
QNode qnode;
QNode* myNode;
QNode* myPred;
}Arg;
typedef struct thread
{
pthread_t t;
Arg arg;
}Thread;
QNode* getAndSet(QNode* qnode)
{
pthread_mutex_lock(&mutex);
QNode* pred = tail;
tail = qnode;
pthread_mutex_unlock(&mutex);
return pred;
}
int isLock()
{
int ret;
QNode* qnode = (QNode*)pthread_getspecific(myPred);
if (qnode == NULL)
return FALSE;
return (qnode->locked)?TRUE:FALSE;
}
void lock()
{
/*得到线程的私有变量。*/
QNode* qnode = (QNode*)pthread_getspecific(myNode);
qnode->locked = TRUE;
QNode* pred = getAndSet(qnode);
pthread_setspecific(myPred, pred);
while(pred->locked)
{
}
}
void unlock()
{
QNode* qnode = (QNode*)pthread_getspecific(myNode);
qnode->locked = FALSE;
QNode* pred = (QNode*)pthread_getspecific(myPred);
pthread_setspecific(myNode, pred);
}
void initCLHlock()
{
q.locked = FALSE;
tail = &q;
}
void initThread(Thread* t, int i)
{
t->arg.qnode.locked = TRUE;
t->arg.myNode = &(t->arg.qnode);
t->arg.myPred = NULL;
t->arg.t_id = i;
}
void* run(Arg* t_arg)
{
/*设置线程的私有变量。此时已经在某一个线程内部,所以会自动的建立map。*/
pthread_setspecific(myPred, t_arg->myPred);
while (1)
{
/*lock*/
lock();
if (shareddata > 0)
{
printf("%d get %dth ticket\n", t_arg->t_id, shareddata);
if (isLock())
printf("locked!\n");
shareddata--;
/*unlock*/
unlock();
}
else
{
/*unlock*/
unlock();
break;
}
}
}
void main()
{
clock_t start, end;
Thread t[10];
initCLHlock();
pthread_key_create(&myNode, NULL);
pthread_key_create(&myPred, NULL);
int i;
for (i=0; i<4; i++)
{
initThread(&t[i], i);
}
/*start*/
start = clock();
for (i=0; i<4; i++)
{
/*创建并执行线程,参数是最后一个参数*/
if (ret != 0)
{
printf("creat_thread error!\n");
exit(0);
}
}
/*join*/
for (i=0; i<4; i++)
{
pthread_join(t[i].t, NULL);
}
end = clock();
printf("shareddata:%d\n", shareddata);
printf("speed %f seconds\n", (double)(end-start)/CLOCKS_PER_SEC);
}
关于pthread_key_t
这个其实是一个hash。每一个pthread_key_t代表一个全局的线程私有变量。也就是说,变量虽然是全局的,但是线程里面对他的改变只改变在线程内部的那个copy。这样做的原因是:因为线程使用的数据都是以参数的形式传进去,这些参数肯定是在线程外部,但是有时候这些变量的该表不需要通知其他线程,仅仅是线程自己使用。像上面这个例子,每个线程只关心自己的myNode与myPred两个指针的指向,而不关心其他线程这两个指针的指向,所以在这种情况下,将两个变量作为线程私有会加快速度。在pthread_getspecific与pthread_setspecific时,通过hash查找到对应的值。