├── Makefile
├── c_flamegraph.svg
├── c_mutex_flamegraph.svg
├── counter_race.c
├── counter_with_atomics.c
├── counter_with_mutex.c
├── counter_with_spinlock.c
├── rust_atomics_flamegraph.svg
├── rust_counter_atomics.rs
├── rust_counter_mutex.rs
└── rust_mutex_flamegraph.svg
/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | gcc -std=c99 -o counter_race counter_race.c -lpthread
3 | gcc -std=c99 -o counter_with_mutex counter_with_mutex.c -lpthread
4 | gcc -std=c99 -o counter_with_spinlock counter_with_spinlock.c -lpthread -D_POSIX_C_SOURCE=200112L
5 | gcc -std=c99 -o counter_with_atomics counter_with_atomics.c -lpthread -D_POSIX_C_SOURCE=200112L
6 | rustc -O rust_counter_mutex.rs
7 | rustc -O rust_counter_atomics.rs
8 |
--------------------------------------------------------------------------------
/c_mutex_flamegraph.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
1149 |
--------------------------------------------------------------------------------
/counter_race.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #define NUM_THREADS 20
5 | #define NUM_INCREMENTS 1000000
6 |
7 | int counter;
8 |
9 | void *AddThings(void *threadid)
10 | {
11 | for (int i = 0; i < NUM_INCREMENTS; i++)
12 | counter += 1;
13 | pthread_exit(NULL);
14 | }
15 |
16 | int main (int argc, char *argv[])
17 | {
18 | pthread_t threads[NUM_THREADS];
19 | long t;
20 | for(t = 0; t
2 | #include
3 | #include
4 | #define NUM_THREADS 20
5 | #define NUM_INCREMENTS 1000000
6 |
7 | int counter;
8 |
9 | void *AddThings(void *threadid)
10 | {
11 | for (int i = 0; i < NUM_INCREMENTS; i++) {
12 | __sync_add_and_fetch(&counter, 1);
13 | }
14 | pthread_exit(NULL);
15 | }
16 |
17 | int main (int argc, char *argv[])
18 | {
19 | pthread_t threads[NUM_THREADS];
20 | long t;
21 | for(t=0; t
2 | #include
3 | #include
4 | #define NUM_THREADS 20
5 | #define NUM_INCREMENTS 1000000
6 |
7 | int counter;
8 | pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
9 |
10 | void *AddThings(void *threadid)
11 | {
12 | for (int i = 0; i < NUM_INCREMENTS; i++) {
13 | pthread_mutex_lock(&mutex);
14 | counter += 1;
15 | pthread_mutex_unlock(&mutex);
16 | }
17 | pthread_exit(NULL);
18 | }
19 |
20 | int main (int argc, char *argv[])
21 | {
22 | pthread_t threads[NUM_THREADS];
23 | long t;
24 | for(t=0; t
2 | #include
3 | #include
4 | #define NUM_THREADS 20
5 | #define NUM_INCREMENTS 1000000
6 |
7 | int counter;
8 | pthread_spinlock_t spinlock;
9 |
10 |
11 | void *AddThings(void *threadid)
12 | {
13 | for (int i = 0; i < NUM_INCREMENTS; i++) {
14 | pthread_spin_lock(&spinlock);
15 | counter += 1;
16 | pthread_spin_unlock(&spinlock);
17 | }
18 | pthread_exit(NULL);
19 | }
20 |
21 | int main (int argc, char *argv[])
22 | {
23 | pthread_spin_unlock(&spinlock);
24 | pthread_t threads[NUM_THREADS];
25 | long t;
26 | for(t=0; t
2 |
3 |
720 |
--------------------------------------------------------------------------------
/rust_counter_atomics.rs:
--------------------------------------------------------------------------------
1 | use std::sync::Arc;
2 | use std::sync::atomic::{AtomicUint, Relaxed};
3 |
4 | const NUM_THREADS: uint = 20;
5 | const NUM_INCREMENTS: uint = 1000000u;
6 |
7 | fn main() {
8 | let counter = Arc::new(AtomicUint::new(0));
9 | let (tx, rx) = channel();
10 | for _ in range(0u, NUM_THREADS) {
11 | let (counter, tx) = (counter.clone(), tx.clone());
12 | spawn(proc() {
13 | for _ in range(0u, NUM_INCREMENTS) {
14 | counter.fetch_add(1, Relaxed);
15 | }
16 | tx.send(());
17 | })
18 | }
19 | // Wait for threads to finish
20 | for _ in range(0u, NUM_THREADS) { rx.recv(); }
21 | println!("{}" , counter.load(Relaxed));
22 | }
23 |
--------------------------------------------------------------------------------
/rust_counter_mutex.rs:
--------------------------------------------------------------------------------
1 | use std::sync::{Arc, Mutex};
2 | const NUM_THREADS: uint = 20;
3 | const NUM_INCREMENTS: uint = 1000000u;
4 |
5 | fn main() {
6 | let data = Arc::new(Mutex::new(0u));
7 | let (tx, rx) = channel();
8 | for _ in range(0u, NUM_THREADS) {
9 | let (data, tx) = (data.clone(), tx.clone());
10 | spawn(proc() {
11 | for _ in range(0u, NUM_INCREMENTS) {
12 | let mut d = data.lock();
13 | *d += 1;
14 | }
15 | tx.send(());
16 | })
17 | }
18 | // Wait for threads to finish
19 | for _ in range(0u, NUM_THREADS) { rx.recv(); }
20 | let d = data.lock();
21 | println!("{}" , *d);
22 | }
23 |
--------------------------------------------------------------------------------