スレッド制御2

3.プライベートデータ(多値キーテクノロジー)

マルチスレッド環境、プロセスのプロセス内のすべてのスレッド、および公共のすべてのスレッドのため、グローバル変数が共有するデータ空間。時には、あなたは自分自身のスレッドグローバル変数を保存する必要があり、グローバル変数はスレッド内でのみ有効で、各機能は、スレッドが、これはキーの多値技術であることをプライベート・グローバル変数にアクセスすることができ、それは、複数の値にキー対応です。

アクセスする場合、データがキーによってアクセスされ、アクセスは変数のように見える、実際のアクセス異なるデータ。

書式#include <pthread.hの> 
int型pthread_key_createの(pthread_key_t *キー、無効(* dest_function)(void *型)); //キー作成
のint pthread_setspecificの(pthread_key_tキー、constの無効 *ポインタ); // スレッドがキープライベートで設定しますデータ
無効* pthread_getspecificの(pthread_key_tキー); // キーのスレッドプライベートからデータを読み込む
int型とpthread_key_delete(pthread_key_tキー); //キーを削除します

 pthread_key_createの:TSDのプールからLinuxディストリビューション、キーを使用するようにアクセスを提供するために、それを割り当てるポインタが空でない場合、キー・ポインタを指すように最初の重要なパラメータは、2番目のパラメータは、関数ポインタでありますスレッドが終了は、関連データを2keyいつ割り当てられたバッファを解放し、パラメータとしてdestr_functionを呼び出します。

キーの値が作成されると、すべてのスレッドが彼へのアクセス権を持って、各スレッドは、キー、多値同じ名前のグローバル変数が異なる値と同等のキー値、埋めるために自分のニーズに応じて提供することができます。

pthread_setspecificの:pthread_setspecificのに関連付けられたキー値の値は、新しいスレッドを指定するための重要な機能である。この関数ポインタは、スレッドは、スペースを再利用するために、元のスレッドデータを解放する必要があります。

pthread_getspecificの:関数によってキーに関連付けられたデータを得ます。

pthread_key_delete:この関数は、キーを削除するために使用され、メモリによって占有されたキーがリリースされます削除します。キーが占有メモリ、および占有キーデータメモリに関連するスレッドを解除されたときに解放されないことに注意してください。このように、リリーススレッドデータは、キーを離す前に完了しなければなりません。

ルーチン

書式#include <stdio.hに> 
する#include <stdlib.h>に含ま
書式#include <unistd.h> 
の#include <pthread.hの> 
書式#include <string.hの> 

pthread_key_tキー。


ボイドFUNC()
{ 
	のprintf( "キーの値は%Dを\ nである"、pthread_getspecificの(キー))。
} 
ボイド*スレッド2(ボイド*の引数)
{ 
	int型TSD = 5。
	printf( "スレッド%ldが\ nを実行している"、pthread_self())。
	pthread_setspecificの(キー、(void *型)TSD); 
	printf( "スレッド2%のLDリターン%d個の\ n"、pthread_self()、pthread_getspecificの(キー))。
	FUNC(); 
} 


ボイド*スレッド1(ボイド*の引数)
{ 
	int型TSD = 0。
	がpthread_t thid2; 
	printf( "スレッド%ldが\ nを実行している"、pthread_self())。
	pthread_create(&thid2、NULL、スレッド2、NULL);
	printf( "スレッド1%ldが\%D戻りN"、pthread_self()、pthread_getspecificの(キー))。
	FUNC(); 
} 
)(メインINT 
{ 
	THIDがpthread_t。
	printf( "メインスレッドは、\ nを実行している始まり"); 
	pthread_key_createの(&キー、NULL); 
	pthread_create(&THID、NULL、スレッド1、NULL); 
	睡眠(3); 
	pthread_key_delete(キー); 
	printf( "メインスレッド終了する\ n"); 
	0を返します。
}

 業績

 

 あなたが見ることができますが、関数funcは、まだ独自のスレッドの値を設定するための鍵である呼び出すときに、各スレッドが返されます。

4.スレッド同期

4.1ミューテックス

キーコードロックの方法を提供することにより、スレッド間の同期を達成するためにマルチスレッド。

ミューテックス機能

#include<pthread.h>
pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);//初始化一个互斥锁
pthread_mutex_destory(pthread_mutex_t *mutex);//注销一个互斥锁
pthread_mutex_unlock(pthread_mutex_t *mutex);//加锁,若不成功,阻塞等待
pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
pthread_mutex_trylock(pthread_mutex_t *mutex);//测试加锁,若不成功立即返回,错误码为EBUSY

 使用互斥锁之前必须先进行初始化操作。初始化的方式有两种,一种是静态赋值法,将宏常量PTHREAD_MUTEX_INITIALIZER赋值给互斥锁

pthread_mutex_t mutex = PTHREAD_MUTEX_INITILIZER;

 另外一种方式就是通过pthread_mutex_init函数初始化互斥,函数原型如上

参数mutexattr表示互斥锁的属性,如果为NULL则使用默认属性。

初始化结束后就可以使用pthread_mutex_lock,pthread_mutex_trylock这两个函数给互斥锁加锁了。

用pthread_mutex_lock()加锁时,如果mutex已经被锁住,当前尝试加锁的线程就会阻塞,直至互斥锁被其他线程释放。当pthread_mutex_lock函数返回时,说明互斥锁已经被当前线程加锁成功。pthread_mutex_lock则不同,若mutex已经被加锁,他将立即返回,返回的错误码为EBUSY,而不是阻塞等待。

注:加锁时,无论何种类型的锁,都不可能同时被两个不同的线程同时获得,其中一个必须等待解锁。在同一进程中的线程,若加锁后没有解锁,其他线程将无法再获得该锁。

锁用完后应当解锁,使用pthread_mutex_unlock函数解锁时,要满足两个条件:一个是互斥锁必须处于加锁状态,二是调用本函数的线程必须是给互斥锁加锁的线程(即加锁前锁还在,谁加锁谁解锁)。

互斥锁使用完毕后,必须进行清除。清除互斥锁使用函数pthread_mutex_destory,函数原型如上。

清除一个互斥锁将会释放它所占用的资源。清除互斥锁时要求锁处于放开的状态。若锁处于锁定状态,函数返回EBUSY,该函数成功执行时返回0。由于在Linux中,互斥锁并不占用内存,因此pthread_mutex_destory()除了解除互斥锁的状态外再无任何作用。

例程(文件读写保护)

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>

#define File  "output.txt"

pthread_mutex_t number_mutex;

void *pthread1(void *arg)
{
	int t = 5;
	while(t)
	{
		write_max(File);
		sleep(1);
	 	--t;
	}
}

void *pthread2(void *arg)
{
	int t = 5;
	while(t)
	{
		read_max(File);
		sleep(1);
		--t;
	}
}
void write_max(char *file)
{
	unsigned long long a = 0;
	int b = 0;
	char timeStr[14], ch;
	time_t timer;
	struct tm *tblock;
	time(&timer);
	tblock = gmtime(&timer);
	a = (tblock->tm_year+1900)*100;
	a = (a+tblock->tm_mon+1)*100;
	a = (a+tblock->tm_mday)*100;
	a = (a+tblock->tm_hour+8)*100;
	a = (a+tblock->tm_min)*100;
	a = (a+tblock->tm_sec);
	sprintf(timeStr, "%llu", a);
	pthread_mutex_lock(&number_mutex);
	FILE *fp;
	fp = fopen(file, "w");
	if(fp == NULL)
	{
		printf("Open file failed\n");
		fclose(fp);
		exit(1);
	}
	while(timeStr[b] != '\0')
	{
		fputc(timeStr[b], fp);
		++b;
	}
	printf("pthread = %ld writing %s to %s\n", pthread_self(), timeStr, file);
	fclose(fp);
	pthread_mutex_unlock(&number_mutex);
}
void read_max(char *file)
{
	char ch[14], *rc = NULL;
	pthread_mutex_lock(&number_mutex);
	FILE *fp;
	fp = fopen(file, "r");
	if(fp == NULL)
	{
		printf("Open file error\n");
		fclose(fp);
		exit(1);
	}
	rc = fgets(ch, 15, fp);
	printf("pthread = %ld, time = %s\n", pthread_self(), ch);
	fclose(fp);
	pthread_mutex_unlock(&number_mutex);
}


int main()
{
	pthread_t th1, th2;
	pthread_create(&th1, NULL, pthread1, NULL);
	pthread_create(&th2, NULL, pthread2, NULL);
	sleep(6);
	return 0;
}

 运行结果

 

 当程序中多个线程都要对一个文件进行读写操作的时候,为保证同步和文件安全,在一个线程对文件进行操作时必须加锁,其余要使用文件的线程先等待锁被释放后随机获得互斥锁。

(将写和读程序的加锁解锁代码都注释以后)

 

 同时对文件操作导致未知的数据出现在文件中。



おすすめ

転載: www.cnblogs.com/area-h-p/p/11599652.html