互斥的彼得森算法设置 1(基本 C 实现)
问题:给定 2 个进程 i 和 j,您需要编写一个程序,无需任何额外的硬件支持即可保证两者之间互斥。
解决方案:可以有多种方法来解决这个问题,但大多数都需要额外的硬件支持。最简单和最流行的方法是使用彼得森算法进行互斥。它是由 Peterson 于 1981 年开发的,尽管在这个方向上的最初工作是由 Theodorus Jozef Dekker 完成的,他在 1960 年提出了 Dekker 算法,后来由 Peterson 改进并被称为Peterson 算法。
基本上,Peterson 的算法通过仅使用共享内存来提供有保证的互斥。它在算法中使用了两个思想:
- 愿意获取锁。
- 转动获取锁。
先决条件:C 中的多线程
解释:
这个想法是首先一个线程表达它想要获取锁的愿望并设置flag[self] = 1 ,然后给另一个线程一个获取锁的机会。如果线程想要获取锁,那么它会获取锁并将机会传递给第一个线程。如果它不想获得锁,那么 while 循环就会中断,第一个线程就有机会了。
C语言实现
C
// Filename: peterson_spinlock.c
// Use below command to compile:
// gcc -pthread peterson_spinlock.c -o peterson_spinlock
#include
#include
#include"mythreads.h"
int flag[2];
int turn;
const int MAX = 1e9;
int ans = 0;
void lock_init()
{
// Initialize lock by reseting the desire of
// both the threads to acquire the locks.
// And, giving turn to one of them.
flag[0] = flag[1] = 0;
turn = 0;
}
// Executed before entering critical section
void lock(int self)
{
// Set flag[self] = 1 saying you want to acquire lock
flag[self] = 1;
// But, first give the other thread the chance to
// acquire lock
turn = 1-self;
// Wait until the other thread looses the desire
// to acquire lock or it is your turn to get the lock.
while (flag[1-self]==1 && turn==1-self) ;
}
// Executed after leaving critical section
void unlock(int self)
{
// You do not desire to acquire lock in future.
// This will allow the other thread to acquire
// the lock.
flag[self] = 0;
}
// A Sample function run by two threads created
// in main()
void* func(void *s)
{
int i = 0;
int self = (int *)s;
printf("Thread Entered: %d\n", self);
lock(self);
// Critical section (Only one thread
// can enter here at a time)
for (i=0; i
C
// mythread.h (A wrapper header file with assert
// statements)
#ifndef __MYTHREADS_h__
#define __MYTHREADS_h__
#include
#include
#include
void Pthread_mutex_lock(pthread_mutex_t *m)
{
int rc = pthread_mutex_lock(m);
assert(rc == 0);
}
void Pthread_mutex_unlock(pthread_mutex_t *m)
{
int rc = pthread_mutex_unlock(m);
assert(rc == 0);
}
void Pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg)
{
int rc = pthread_create(thread, attr, start_routine, arg);
assert(rc == 0);
}
void Pthread_join(pthread_t thread, void **value_ptr)
{
int rc = pthread_join(thread, value_ptr);
assert(rc == 0);
}
#endif // __MYTHREADS_h__
C
// mythread.h (A wrapper header file with assert
// statements)
#ifndef __MYTHREADS_h__
#define __MYTHREADS_h__
#include
#include
#include
void Pthread_mutex_lock(pthread_mutex_t *m)
{
int rc = pthread_mutex_lock(m);
assert(rc == 0);
}
void Pthread_mutex_unlock(pthread_mutex_t *m)
{
int rc = pthread_mutex_unlock(m);
assert(rc == 0);
}
void Pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg)
{
int rc = pthread_create(thread, attr, start_routine, arg);
assert(rc == 0);
}
void Pthread_join(pthread_t thread, void **value_ptr)
{
int rc = pthread_join(thread, value_ptr);
assert(rc == 0);
}
#endif // __MYTHREADS_h__
输出:
Thread Entered: 1
Thread Entered: 0
Actual Count: 2000000000 | Expected Count: 2000000000
产生的输出是 2*10 9 ,其中 10 9由两个线程递增。