Поиск…
Простая тема без аргументов
Этот базовый пример рассчитывается с разной скоростью по двум потокам, которые мы называем синхронизацией (основной) и асинхронной (новый поток). Основной поток подсчитывается до 15 с частотой 1 Гц (1 с), а второй - до 10 на 0,5 Гц (2 с). Поскольку основной поток заканчивается раньше, мы используем pthread_join
чтобы заставить его ждать завершения async.
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
/* This is the function that will run in the new thread. */
void * async_counter(void * pv_unused) {
int j = 0;
while (j < 10) {
printf("async_counter: %d\n", j);
sleep(2);
j++;
}
return NULL;
}
int main(void) {
pthread_t async_counter_t;
int i;
/* Create the new thread with the default flags and without passing
* any data to the function. */
if (0 != (errno = pthread_create(&async_counter_t, NULL, async_counter, NULL))) {
perror("pthread_create() failed");
return EXIT_FAILURE;
}
i = 0;
while (i < 15) {
printf("sync_counter: %d\n", i);
sleep(1);
i++;
}
printf("Waiting for async counter to finish ...\n");
if (0 != (errno = pthread_join(async_counter_t, NULL))) {
perror("pthread_join() failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Скопировано здесь: http://stackoverflow.com/documentation/c/3873/posix-threads/13405/simple-thread-without-arguments, где он первоначально был создан М. Рубио-Роем .
Простое использование Mutex
Библиотека потоков POSIX обеспечивает реализацию примитива mutex, используемого для взаимного исключения. Mutex создается с помощью pthread_mutex_init
и уничтожается с помощью pthread_mutex_destroy
. Получение мьютекса может быть выполнено с помощью pthread_mutex_lock
или pthread_mutex_trylock
(в зависимости от желательности тайм-аута) и освобождения мьютекса выполняется через pthread_mutex_unlock
.
Ниже приведен простой пример использования мьютекса для сериализации доступа к критическому разделу. Во-первых, пример без использования мьютекса. Обратите внимание, что эта программа имеет гонку данных из-за несинхронизированного доступа к global_resource
двумя потоками. В результате эта программа имеет неопределенное поведение :
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
// Global resource accessible to all threads
int global_resource;
// Threading routine which increments the resource 10 times and prints
// it after every increment
void* thread_inc (void* arg)
{
for (int i = 0; i < 10; i++)
{
global_resource++;
printf("Increment: %d\n", global_resource);
// Make this thread slower, so the other one
// can do more work
sleep(1);
}
printf("Thread inc finished.\n");
return NULL;
}
// Threading routine which decrements the resource 10 times and prints
// it after every decrement
void* thread_dec (void* arg)
{
for (int i = 0; i < 10; i++)
{
global_resource--;
printf("Decrement: %d\n", global_resource);
}
printf("Thread dec finished.\n");
return NULL;
}
int main (int argc, char** argv)
{
pthread_t threads[2];
if (0 != (errno = pthread_create(&threads[0], NULL, thread_inc, NULL)))
{
perror("pthread_create() failed");
return EXIT_FAILURE;
}
if (0 != (errno = pthread_create(&threads[1], NULL, thread_dec, NULL)))
{
perror("pthread_create() failed");
return EXIT_FAILURE;
}
// Wait for threads to finish
for (int i = 0; i < 2; i++)
{
if (0 != (errno = pthread_join(threads[i], NULL))) {
perror("pthread_join() failed");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
Возможный выход:
Increment: 1
Decrement: 0
Decrement: -1
Decrement: -2
Decrement: -3
Decrement: -4
Decrement: -5
Decrement: -6
Decrement: -7
Decrement: -8
Decrement: -9
Thread dec finished.
Increment: -8
Increment: -7
Increment: -6
Increment: -5
Increment: -4
Increment: -3
Increment: -2
Increment: -1
Increment: 0
Thread inc finished.
Теперь, если мы хотим синхронизировать эти потоки, чтобы мы сначала хотели увеличивать или уменьшать весь путь вверх или вниз, а затем делать это по-другому, нам нужно использовать примитив синхронизации, такой как mutex:
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
// Global resource accessible to all threads
int global_resource;
// Mutex protecting the resource
pthread_mutex_t mutex;
// Threading routine which increments the resource 10 times and prints
// it after every increment
void* thread_inc (void* arg)
{
// Pointer to mutex is passed as an argument
pthread_mutex_t* mutex = arg;
// Execute the following code without interrupts, all the way to the
// point B
if (0 != (errno = pthread_mutex_lock(mutex)))
{
perror("pthread_mutex_lock failed");
exit(EXIT_FAILURE);
}
for (int i = 0; i < 10; i++)
{
global_resource++;
printf("Increment: %d\n", global_resource);
// Make this thread slower, so the other one
// can do more work
sleep(1);
}
printf("Thread inc finished.\n");
// Point B:
if (0 != (errno = pthread_mutex_unlock(mutex)))
{
perror("pthread_mutex_unlock failed");
exit(EXIT_FAILURE);
}
return NULL;
}
// Threading routine which decrements the resource 10 times and prints
// it after every decrement
void* thread_dec (void* arg)
{
// Pointer to mutex is passed as an argument
pthread_mutex_t* mutex = arg;
if (0 != (errno = pthread_mutex_lock(mutex)))
{
perror("pthread_mutex_lock failed");
exit(EXIT_FAILURE);
}
for (int i = 0; i < 10; i++)
{
global_resource--;
printf("Decrement: %d\n", global_resource);
}
printf("Thread dec finished.\n");
// Point B:
if (0 != (errno = pthread_mutex_unlock(mutex)))
{
perror("pthread_mutex_unlock failed");
exit(EXIT_FAILURE);
}
return NULL;
}
int main (int argc, char** argv)
{
pthread_t threads[2];
pthread_mutex_t mutex;
// Create a mutex with the default parameters
if (0 != (errno = pthread_mutex_init(&mutex, NULL)))
{
perror("pthread_mutex_init() failed");
return EXIT_FAILURE;
}
if (0 != (errno = pthread_create(&threads[0], NULL, thread_inc, &mutex)))
{
perror("pthread_create() failed");
return EXIT_FAILURE;
}
if (0 != (errno = pthread_create(&threads[1], NULL, thread_dec, &mutex)))
{
perror("pthread_create() failed");
return EXIT_FAILURE;
}
// Wait for threads to finish
for (int i = 0; i < 2; i++)
{
if (0 != (errno = pthread_join(threads[i], NULL))) {
perror("pthread_join() failed");
return EXIT_FAILURE;
}
}
// Both threads are guaranteed to be finished here, so we can safely
// destroy the mutex
if (0 != (errno = pthread_mutex_destroy(&mutex)))
{
perror("pthread_mutex_destroy() failed");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Одним из возможных
Increment: 1
Increment: 2
Increment: 3
Increment: 4
Increment: 5
Increment: 6
Increment: 7
Increment: 8
Increment: 9
Increment: 10
Thread inc finished.
Decrement: 9
Decrement: 8
Decrement: 7
Decrement: 6
Decrement: 5
Decrement: 4
Decrement: 3
Decrement: 2
Decrement: 1
Decrement: 0
Thread dec finished.
Другой возможный выход был бы обратным, в случае, если thread_dec
получил мьютекс.