Named semaphore

(1) Name: "/myname" note: the name must start with a /Copy the code

How do I use this semaphore?

Sem_close (); sem_unlink(); sem_unlink(); sem_unlink()Copy the code

1. Open the semaphore with sem_open()

Sem_wait (); sem_post()

Sem_close () to close the semaphore, sem_unlink() to delete the semaphore, release resources

The sample code

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <semaphore.h>

char str[20];

#define SPACE "/space"
#define DATA "/data"

sem_t *space;
sem_t *data; 

void *func1(void *arg)  		
{
	while(1)
	{	
		//P operation space resource -1
		sem_wait(space);
		scanf("%s", str);
		//V Operation data resource +1sem_post(data); }}void *func2(void *arg)			
{
	while(1)
	{
		//P Operation data resource -1
		sem_wait(data);
		printf("%s\n", str);
		//V Operation space resource +1sem_post(space); }}void f(int sig)
{
	sem_close(space);
	sem_unlink(SPACE);
	sem_close(data);
	sem_unlink(DATA);
	exit(0);
}

int main(int argc, char const *argv[])
{
	//
	signal(2, f);


	void *p[2] = {func1, func2};
	
	pthread_t pid[2];
	for (int i = 0; i < 2; ++i)
	{
		pthread_create(&pid[i], NULL, p[i], NULL);
	}

	space = sem_open(SPACE, O_CREAT, 0666.1);
	data = sem_open(DATA, O_CREAT, 0666.0);

	while(1);


	return 0;
}
Copy the code

The results

Unknown semaphore

The steps to use this semaphore are:

1. Define such a variable (such as a global variable) in an area accessible to all of these threads. The type is sem_t. 2. Initialize it with sem_init() before any thread uses it. 3, use sem_wait()/sem_trywait() and sem_post() to perform P and V operations, respectively. 4. When no longer needed, use sem_destroy() to destroy it.Copy the code

The sample code

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <semaphore.h>

char str[20];

sem_t space;
sem_t data; 

void *func1(void *arg)  		
{
	while(1)
	{	
		//P operation space resource -1
		sem_wait(&space);
		scanf("%s", str);
		//V Operation data resource +1sem_post(&data); }}void *func2(void *arg)			
{
	while(1)
	{
		//P Operation data resource -1
		sem_wait(&data);
		printf("%s\n", str);
		//V Operation space resource +1sem_post(&space); }}void f(int sig)
{
	sem_destroy(&data);
	sem_destroy(&space);	
	exit(0);
}

int main(int argc, char const *argv[])
{
	//
	signal(2, f);

	sem_init(&space, 0.1);			// Space resources (write resources) 1
	sem_init(&data, 0.0);			// Data resource (read resource) 0

	void *p[2] = {func1, func2};
	
	pthread_t pid[2];
	for (int i = 0; i < 2; ++i)
	{
		pthread_create(&pid[i], NULL, p[i], NULL);
	}

	
	while(1);


	return 0;
}
Copy the code

Exclusive locks:

Pthread_mutex_t m; // Define a mutex variable

// Initialize pthread_mutex_init(&m, NULL); / / lock pthread_mutex_lock (& m); / / unlock pthread_mutex_unlock (& m); Pthread_mutex_destroy (&m);Copy the code

 

Using mutex is prone to deadlocks

(1) Deadlocks may occur when two locks are unlocked alternately by multiple threads

Pthread_mutex_lock(&m1); Printf(" Do a 2s thing "); Sleep(2); Pthread_mutex_lock(&m2); Pthread_mutex_unlock(&m1); Pthread_mutex_unlock(&m2); Pthread_mutex_lock(&m2); Printf(" Do a 2s thing "); Sleep(2); Pthread_mutex_lock(&m1); Pthread_mutex_unlock(&m2); Pthread_mutex_unlock(&m1);Copy the code

(2) If a thread is abnormally killed without unlocking after it is locked, other threads that need to acquire the same lock will be blocked

(3) After a task is locked, the same lock will also appear deadlock before unlocking

So:

Create a cancellation routine for the thread, freeing what might not be freed

Try to avoid locking the same lock or other locks in the process of unlocking a set of locks

The mutex should not protect a critical section that is too long, nor should it nest too many functions

Sample code:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <semaphore.h>

// Define a mutex variable
pthread_mutex_t m;
pthread_mutex_t m1;

int num;

void *func1(void *arg)
{
	while(1)
	{
		/ / lock
		pthread_mutex_lock(&m);
		scanf("%d", &num);
		/ / unlock
		pthread_mutex_unlock(&m);
		usleep(10); }}void *func2(void *arg)
{
	sleep(1);
	while(1)
	{
		/ / lock
		pthread_mutex_lock(&m);
		printf("num = %d\n", num);
		/ / unlock
		pthread_mutex_unlock(&m);
		usleep(10); }}int main(int argc, char const *argv[])
{
	// Initialize the mutex
	pthread_mutex_init(&m, NULL);
	pthread_mutex_init(&m1, NULL);

	// Create two threads
	pthread_t pid1, pid2;

	pthread_create(&pid1, NULL, func1, NULL);
	pthread_create(&pid2, NULL, func2, NULL);

	while(1) {}return 0;
}
Copy the code

 

Read and write locks:

Read/write locks are almost the same as mutex locks. The only difference is that when adding locks, you can choose to add write locks or read locks. Only one write lock can be added, while multiple read locks can be added

// define the read/write lock variable Pthread_rwlock_t rwlock; // Initialize the read/write lock Pthread_rwlock_init(&rwlock, NULL); // read lock Pthread_rwlock_rdlock(&rwlock); // write lock Pthread_rwlock_wrlock(&rwlock); / / unlock Pthread_rwlock_unlock (& rwlock); // Pthread_rwlock_destroy(&rwlock);Copy the code

The sample code

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <semaphore.h>

// Define a read/write lock variable
pthread_rwlock_t rwlock;

int num;

void dent(a)
{
	pthread_rwlock_rdlock(&rwlock);
	printf("Lock state of thread 1 \n");
	pthread_rwlock_unlock(&rwlock);
}

void dent1(a)
{
	pthread_rwlock_wrlock(&rwlock);
	printf("Lock state of thread 2 \n");
	pthread_rwlock_unlock(&rwlock);
}

void *func1(void *arg)
{
	while(1)
	{
		/ / write locks
		pthread_rwlock_rdlock(&rwlock);
		scanf("%d", &num);
		/ / unlock
		pthread_rwlock_unlock(&rwlock);
		dent();
		usleep(1000); }}void *func2(void *arg)
{
	sleep(1);
	while(1)
	{
		/ / read lock
		pthread_rwlock_wrlock(&rwlock);
		printf("num2 = %d\n", num);
		/ / unlock
		pthread_rwlock_unlock(&rwlock);
		dent1();
		usleep(1000); }}int main(int argc, char const *argv[])
{
	// Initialize the read/write lock
	pthread_rwlock_init(&rwlock, NULL);

	// Create two threads
	pthread_t pid1, pid2;

	pthread_create(&pid1, NULL, func1, NULL);
	pthread_create(&pid2, NULL, func2, NULL);


	while(1) {}return 0;
}
Copy the code

The results

Conditional variable:

Pthread_cond_t cond; // initialize Pthread_cond_init(&cond, 0); // Destroy the condition variable Pthread_cond_destroy(&cond);Copy the code

Pthread_cond_wait(&cond, &m); Struct timespec t; Pthread_cond_timedwait(&cond, &m, &t);Copy the code

// Wake up a Pthread_cond_signal(&cond); // Wake up all Pthread_cond_broadcast(&cond);Copy the code

The sample code

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <semaphore.h>

// Define mutex variables
pthread_mutex_t m;

// Define the variable of the conditional variable
pthread_cond_t v;

int money = 0;
int flag = 0;

void *func1(void *arg)	/ / small nan
{
	/ / lock
	pthread_mutex_lock(&m);
	while(money < 100)
	{
		pthread_cond_wait(&v, &m);// Enter the condition variable wait queue
	}

	money -=100;
	printf("Xiao Nan takes money 100\ N");
	sleep(1);
	pthread_mutex_unlock(&m);
}

void *func2(void *arg)	/ / xiao Ming
{
	/ / lock
	pthread_mutex_lock(&m);
	while(money < 100)
	{
		pthread_cond_wait(&v, &m);// Enter the condition variable wait queue
	}
	money -=100;
	printf("Xiao Ming takes money 100\n");
	sleep(1);
	pthread_mutex_unlock(&m);
}

int main(int argc, char const *argv[])
{
	// Initialize the mutex
	pthread_mutex_init(&m, NULL);
	// Initialize the condition variable
	pthread_cond_init(&v, 0);

	pthread_t pid1, pid2;
	pthread_create(&pid1, NULL ,func1, NULL);
	pthread_create(&pid2, NULL ,func2, NULL);
	sleep(1);

	
	
	pthread_mutex_lock(&m);

	sleep(3);
	money += 300;
	pthread_cond_broadcast(&v);/ / wake
	pthread_mutex_unlock(&m);
	


	pthread_join(pid1, NULL);
	pthread_join(pid2, NULL);

	// Destroy the lock and condition variables
	pthread_mutex_destroy(&m);
	pthread_cond_destroy(&v);

	return 0;
}
Copy the code

The results

Comparison of several thread-safety mechanisms:

Read/write lock: the use and mutex are basically the same, the difference is lock read lock and write lock (in the case of a large number of critical resources) semaphore: P/V operation, as long as the semaphore is greater than 0 can be P conditional variable: A mutex enhancement that allows something to be done when a condition arises (not in all cases, threads can access critical resources through the mutex, but when required)Copy the code

 

The thread pool:

1. There is no task in the task queue at the beginning, it is an empty chain queue with a head node. 2. Use mutex to protect the queue. 3. Use condition variables to represent changes in the number of tasks in the queue - if the main thread puts tasks on the queue in the future, the condition variable can be used to wake up those threads that are asleep. Thread exit is controlled by a common switch, shutdown, which destroys the entire thread pool.Copy the code

 

API interface

A thread pool-related structure

Represents a taskThe thread pool

Initialize the thread pool

2. Add a task

3. Add active threads

Delete the active thread

Destroy the thread pool