开发使用多线程过程中, 不可避免的会出现多个线程同时操作同一块共享资源, 当操作全部为读时, 不会出现未知结果, 一旦当某个线程操作中有写操作时, 就会出现数据不同步的事件. 

    而出现数据混乱的原因:

    • 资源共享(独享资源则不会)

    • 调试随机(对数据的访问会出现竞争)

    • 线程间缺少必要的同步机制   

    以上三点, 前两点不能被改变. 欲提高效率, 传递数据, 资源必须共享. 只要资源共享, 就一定会出现线程间资源竞争, 只要存在竞争关系, 数据就会出现混乱.

    所以只能从第三点着手, 使多个线程在访问共享资源的时候, 出现互斥.


线程同步:

    指在一定的时间里只允许某一个进程访问某个资源,而在此时间内,不允许其它线程对该资源进行操作.

    

    在使用锁的时候, 以下会出现死锁状态.

    • 线程试图对一把锁进行加锁两次

    • 哲学家就餐[N个哲学家, N支筷子, 哲学家同时对一个方向取筷子, 取到后需要拿另一方面的场子才可以就餐]  


    线程试图对一把锁进行加锁两次:

    

#include 
#include 
#include 
#include 
/*
 *   模拟一个线程对一把锁进行加锁两次
 *   author sea time 2016/06/15
 */

//创建一把互斥锁, 并进行静态初始化
pthread_mutex_t mutex =  PTHREAD_MUTEX_INITIALIZER;

//线程函数
void* thread_handler(void* args){
	//第一次获取锁成功
	pthread_mutex_lock(&mutex);
	//成功获取打印
	printf("get mutex 1 successfully!\n");
	//第二次获取同一把锁
	pthread_mutex_lock(&mutex);
	printf("get mutex 2 successfully!\n");
	pthread_mutex_unlock(&mutex);
	pthread_mutex_unlock(&mutex);
	
	pthread_exit(NULL);
}

int main(int argc, char* argv[]){
	pthread_t tid;
	pthread_create(&tid, NULL, thread_handler, NULL);

	//等待线程结束
	pthread_join(tid, NULL);

	//释放互斥锁
	pthread_mutex_destroy(&mutex);
	return 0;
}

    运行结果:

    wKioL1dhcbXCI0_0AAAt9kDZn90862.png-wh_50

    结果如预期所至, 一直阻塞在那获取锁.


    哲学家就餐[N个哲学家, N支筷子, 哲学家同时对一个方向取筷子, 取到后需要拿另一方面的场子才可以就餐]:


    

#include 
#include 
#include 
#include 
#include 
/*
 *	模拟哲学家用餐模型
 *  author sea time 2016/0615
 */
 //用五把锁模拟五支筷子
pthread_mutex_t mutex[5];

void* thread_handler(void* args){
	//获取当前位数
	long i = (long)args;
	int left, right;
	//当是最后一个哲学家
	if(sizeof(mutex)/sizeof(*mutex) == i + 1){
		left = i;
		right = 0;
	}
	else{
		left = i;
		right = i + 1;
	}
	//获取左边的筷子
	pthread_mutex_lock(&mutex[left]);
	//等待100毫秒, 让其它线程都拿到自己右边的筷子
	usleep(100);
	//获取右边的筷子
	pthread_mutex_lock(&mutex[right]);
	sleep(2);
	printf("%ld 吃完了....!\n", i);
	//解锁
	pthread_mutex_unlock(&mutex[right]);
	//解锁
	pthread_mutex_unlock(&mutex[left]);

	pthread_exit(NULL);
}
int main(int argc, char* argv[]){
	long i = 0;
	int ret = 0;
	pthread_t tid[5];
	

	//初始化五把锁
	for(i = 0; i < sizeof(mutex)/sizeof(*mutex); i++){
		pthread_mutex_init(mutex+i, NULL);
	}

	//创建五个线程
	for(i = 0; i < sizeof(tid)/sizeof(*tid); i++){
		pthread_create(tid+i, NULL, thread_handler, (void*)i);
	}

	//等待线程
	for(i = 0; i < sizeof(tid) / sizeof(*tid); i++){
		pthread_join(tid[i], NULL);
	}
	
	//释放五把锁
	for(i = 0; i < sizeof(mutex)/sizeof(*mutex); i++){
		pthread_mutex_destroy(mutex+i);
	}
	return ret;
}

    运行结果: 会一直阻塞


结论: 在访问共享资源前加锁,访问结束后立即解锁。锁的“粒度”应越小越好。