本文共 3119 字,大约阅读时间需要 10 分钟。
#include#include #include #include #define MODE 4pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*本质就是CPU提供了一个叫做 CPMXCHG 的指令,可以让我们的比较操作和置换操作在一句指令内完成,因为指令是粒度最小的,所以就是原子操作。既然是原子操作,就不用加锁了。但是为了多线程下操作成功,必须使用while循环多次retry。虽然没有像mutex一样sleep-waiting有上下文切换开销,但是CAS会陷入busy-waiting,一直在忙等,类似自旋锁,造成cpu升高。需要评估锁的粒度后使用。*/unsigned long CAS(volatile unsigned int *addr, unsigned int old, unsigned int new){ /* https://www.felixcloutier.com/x86/cmpxchg: (* Accumulator = AL, AX, EAX, or RAX depending on whether a byte, word, doubleword, or quadword comparison is being performed *) TEMP ← DEST IF accumulator = TEMP (比较) THEN ZF ← 1; DEST ← SRC; ELSE ZF ← 0; accumulator ← TEMP; DEST ← TEMP; FI; Compares the value in the AL, AX, EAX, or RAX register with the first operand (destination operand). If the two values are equal, the second operand (source operand) is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, EAX or RAX register. RAX register is available only in 64-bit mode. */ int ret = 0; __asm__ volatile (" lock; cmpxchg %2, %3" : "=a" (ret), "=m"(*addr) : "r" (new), "m" (*addr), "0" (old) : "cc" ); return ret==old;}void* add_cas(void *arg) { int *count = (int *)arg; int old_count; for (int i = 0; i < 2500; i++) { do { old_count = *count; } while (!CAS(count, old_count, old_count + 1)); //} while (!__sync_bool_compare_and_swap(count, old_count, old_count + 1)); } return NULL;}void* add_atomic(void *arg) { int *count = (int *)arg; for (int i = 0; i < 500; i++) { __asm__ __volatile__ ("lock; add %1, %0" : "+m" (*count) : "g" (1) ); } return NULL;}void* add_generic(void *arg){ int *count = (int *)arg; for (int i = 0; i < 500; i++) { (*count)++; } return NULL;}void* add_mutex(void *arg){ int *count = (int *)arg; for (int i = 0; i < 500; i++) { pthread_mutex_lock(&mutex); (*count)++; pthread_mutex_unlock(&mutex); } return NULL;}#define MAXTHREADS 5int main(){ for (int i = 0; i < 500; i++) { pthread_t pth[MAXTHREADS]; int *count = calloc(1, sizeof(int)); for (int i = 0; i < MAXTHREADS; i++) { #if MODE == 1 pthread_create(pth + i, NULL, add_generic, count);#elif MODE == 2 pthread_create(pth + i, NULL, add_mutex, count);#elif MODE == 3 pthread_create(pth + i, NULL, add_atomic, count);#elif MODE == 4 pthread_create(pth + i, NULL, add_cas, count);#endif /* if MODE == 1 */ } for (int i = 0; i < MAXTHREADS; i++) { pthread_join(pth[i], NULL); } printf("count: %d\n", *count); free(count); count = NULL; } return 0;}
转载地址:http://oecii.baihongyu.com/