We worked on Seawulf
ssh seawulfLast login: Thu Nov 20 12:11:49 2025 from 172.20.24.214first let’s make a new folder:
mkdir timewe will work inside that folder
cd time/we made a small C program:
nano sq_sum_threaded.c1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29#include <stdlib.h> #include <stdio.h> #include <pthread.h> /* single global variable */ /* shared, accessible, modifiable by all threads */ int accum = 0; void* square(void* x) { int xi = (int)x; accum += xi * xi; return NULL; /* nothing to return, prevent warning */ } int main(int argc, char** argv) { int i; pthread_t ths[20]; for (i = 0; i < 20; i++) { pthread_create(&ths[i], NULL, square, (void*)(i + 1)); } for (i = 0; i < 20; i++) { void* res; pthread_join(ths[i], &res); } printf("accum = %d\n", accum); return 0; }
then built it
gcc -pthread -g -o sqsum sq_sum_threaded.c -lmsq_sum_threaded.c: In function ‘square’:
sq_sum_threaded.c:10:12: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
int xi = (int)x;
^
sq_sum_threaded.c: In function ‘main’:
sq_sum_threaded.c:19:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&ths[i], NULL, square, (void*)(i + 1));
^we got a few warning but they’re okay for what we are doing today
we see that it created an executable
lssqsum sq_sum_threaded.cNow, let’s test our program
./sqsumaccum = 2870this looks right
To do so we will run it 100000 times with a loop also uses some new bash commands:
sortorders all of the outputs of the 1000 runs of our programand
uniqwith the-coption counts how many times any given result appeart multiple times
for i in {1..100000}; do ./sqsum ; done | sort |uniq -c 1 accum = 2193
1 accum = 2240
1 accum = 2257
6 accum = 2470
24 accum = 2509
32 accum = 2546
17 accum = 2581
37 accum = 2614
1 accum = 2638
23 accum = 2645
1 accum = 2649
27 accum = 2674
1 accum = 2689
16 accum = 2701
30 accum = 2726
21 accum = 2749
19 accum = 2770
28 accum = 2789
1 accum = 2797
21 accum = 2806
24 accum = 2821
25 accum = 2834
41 accum = 2845
1 accum = 2850
131 accum = 2854
1 accum = 2857
183 accum = 2861
101 accum = 2866
9 accum = 2869
99176 accum = 2870It’s not correct all the time!
Let’s try another program
cp sq_sum_threaded.c count_threaded.cnano count_threaded.c#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
/* single global variable */
/* shared, accessible, modifiable by all threads */
int accum = 0;
void* counter(void* x) {
int xi = (int)x;
accum ++;
return NULL; /* nothing to return, prevent warning */
}
int main(int argc, char** argv) {
int i;
pthread_t ths[2000];
for (i = 0; i < 2000; i++) {
pthread_create(&ths[i], NULL, counter, (void*)(i + 1));
}
for (i = 0; i < 20; i++) {
void* res;
pthread_join(ths[i], &res);
}
printf("accum = %d\n", accum);
return 0;
}then build
gcc -pthread -g -o count_th count_threaded.c -lmand run
for i in {1..1000}; do ./count_th ; done | sort |uniq -c 1 accum = 1612
1 accum = 1657
1 accum = 1669
1 accum = 1675
1 accum = 1705
1 accum = 1710
1 accum = 1721
1 accum = 1752
1 accum = 1766
1 accum = 1775
1 accum = 1780
1 accum = 1784
1 accum = 1788
1 accum = 1790
1 accum = 1791
1 accum = 1799
1 accum = 1810
1 accum = 1819
1 accum = 1825
1 accum = 1828
1 accum = 1831
1 accum = 1840
1 accum = 1841
1 accum = 1842
1 accum = 1845
1 accum = 1846
1 accum = 1847
1 accum = 1848
1 accum = 1855
1 accum = 1858
1 accum = 1863
1 accum = 1871
1 accum = 1883
1 accum = 1890
1 accum = 1895
1 accum = 1914
1 accum = 1962
1 accum = 1983
1 accum = 1985
1 accum = 1986
1 accum = 1987
1 accum = 1988
2 accum = 1989
2 accum = 1990
2 accum = 1991
3 accum = 1992
8 accum = 1993
5 accum = 1994
7 accum = 1995
21 accum = 1996
19 accum = 1997
40 accum = 1998
106 accum = 1999
743 accum = 2000We get a lot of different answers again.
This computation is even simpler! What is going on?
Understanding Race Conditions¶
To understand what happens and why it is called a race condition, lets look at the following program, which should be an equivalent way to implement the body of the square function.
11accum += xi * xi;
and this how it actually happens
int temp = accum;
temp += x * x;
accum = temp;In this one, we first copy the accum value to a temporary variable, then square the value and add that to temp, and then finally add that value back to accum. This should be equivalent to the program above, result wise.
That is, when the CPU gets to this line, in order to execute it, it has to:
compute the product
read the value of
accumfrom memory to a registeradd the product and
accumwrite
accumback to memory from the ALU output
Even though this is not how we wrote our program, this is actually what it has to do, as we spin out each thread.
This table traces through what occurs in two threads.
// Thread 1 | // Thread 2 | Status |
|
| now |
`temp2 += 2 * 2; | now temp2 = 4 | |
temp1 += 1 * 1; | // temp1 = 1 | |
accum = temp1; | // accum = 1 | |
accum = temp2; | // accum = 4 |
So, what happens is each thread looks at the current value of accum and stores it to a thread-specific temporary variable. Each thread has its own memory, but they do all share the global variables.
Then thread 2 completes its calculation and updates temp2 and thread 1 updates temp1. So far everything is okay, but next thread 1 writes to accum and sets it to 1, and finally thread to writes to accum and makes it 4. The two values from the threads did not get added together, because thread 2 started before thread 1 finished.
So, we end up losing some of the values.
Locking¶
We can instead change our square function. First we copy it
cp sq_sum_threaded.c sq_sum_locked.cnano count_threaded.cfor i in {1..1000}; do ./count_th ; done | sort |uniq -c 1 accum = 1986
1 accum = 1989
2 accum = 1990
1 accum = 1991
1 accum = 1992
1 accum = 1994
2 accum = 1995
7 accum = 1996
10 accum = 1997
44 accum = 1998
194 accum = 1999
736 accum = 2000cp sq_sum_threaded.c sq_sum_locked.cnano sq_sum_locked.ccat sq_sum_locked.c#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
/* single global variable */
/* shared, accessible, modifiable by all threads */
int accum = 0;
pthread_mutex_t accum_mutex = PTHREAD_MUTEX_INITIALIZER;
void* square(void* x) {
int xi = (int)x;
int temp = xi * xi;
pthread_mutex_lock(&accum_mutex);
accum += temp;
pthread_mutex_unlock(&accum_mutex);
return NULL; /* nothing to return, prevent warning */
}
int main(int argc, char** argv) {
int i;
pthread_t ths[20];
for (i = 0; i < 20; i++) {
pthread_create(&ths[i], NULL, square, (void*)(i + 1));
}
for (i = 0; i < 20; i++) {
void* res;
pthread_join(ths[i], &res);
}
printf("accum = %d\n", accum);
return 0;
}gcc -pthread -g -o sq_sum_l sq_sum_locked.c -lmsq_sum_locked.c: In function ‘square’:
sq_sum_locked.c:11:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
int xi = (int)x;
^
sq_sum_locked.c: In function ‘main’:
sq_sum_locked.c:25:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&ths[i], NULL, square, (void*)(i + 1));
^for i in {1..1000}; do ./sq ; done | sort |uniq -csqsum sq_sum_lfor i in {1..1000}; do ./sq_sum_l ; done | sort |uniq -c 1000 accum = 2870With the lock it works correctly every time.
von Neumann Architecture¶

what else do we need besides ALU for to have like a whole computer
What is a computer?¶
How have computers changed over time?
at the physical level
what was the context and motivation for these advances?
how does that context influence how we use computers today?
how does that influence computing as a discipline?
Let’s start with a dictionary¶
we can start with a dictionary
note that this starts with reference to a person.
Computers as people¶
and this text this particular dictionary is useful because it also includes where does the term originated like where does in that particular usage start appearing and so these are these are pretty all right this is starting 1646 1707
Use of the word computer to refer to the person still common how recently 1950s
the movie hidden figures is available on Disney+ with subscription or other streaming platforms for ~$4 streaming rental.
the book hidden figures is available at URI’s library
Computers as Machines¶
Computers as machines started later. We started with mechanical, analog and then moved to electronic and then digital.
How much do we talk about computers?¶
how much do we talk about them changes over time
Mechanical Calculators¶
how do we actually like physically make it be machine
well we’ve we’ve talked we handed out that like it’s going to reduce down to or isn’t my check and logical operations write those de back much further than

what is the mechanical calculator it works by like incrementing it doesn’t do the logic like they took not a binary representation it’s not adding via input two numbers and then it goes forward its where’s my income as you put in one number then you can add the next number and it kind of works the wheels have like the numbers on them and it uses like 9 supplement to carry over to the next bit so there’s a gear that when it hits a certain point that turns the next year and then it goes for it any Castles in the Sky why the semi did
Why did he make this?
He was 18 and his father was a tax commissioner in France and he wanted to like reduce his father’s workload
so he invented this calulator machine and received royal privilege from France in 1649 to be only person allowed to build a manufactured Computing a calculator is like mechanical calculators

Contrast this royal privelege with the 1970s where in resolving some other conflict, a court that declared the content of the computer cannot be copyrighted and it’s free for anyone to use the concept of a computer
Early Computers¶
first vaccuum tubes: or diodes
diodes prevent flow of electricity in one direction and allow in the other. they can be used to create circuits that behave like the logical operations, and create the gates.
diodes only are easy for
&and|gates,transistors can operate as a switch or amplifier and can also be used to build logic gates they’re faster, smaller, and better at more types of gates than diodes
Prepare for Next Class¶
Preview the Stack Overflow Developer Survey Technology section parts that are about programming languages. Create dev_insights.md with 3-5 bullet points for discussion. These can be facts you found most interesting or questions you have based on the results (it can be clarifying or deeper questions)
Badges¶
Review the notes from today
Examine the assembly for the
sq_sum_threaded.cwe wrote in class and find the lines that show why the race condition occurs. Describe how you figured it out and include the relevant lines in race.md.
Review the notes from today
Research examples of programs using multi-threading besides splitting up a single calculation for time reasons, include three examples in whymultithread.md.
Examine the assembly for the
sq_sum_threaded.cwe wrote in class and find the lines that show why the race condition occurs. Describe how you figured it out and include the relevant lines in race.md.Read about systems abstractions in CACM and answer reflection questions below in systemsabstractions.md based on the systems abstraction reading:
1. What are your overall thoughts on this article? (include how much is neew vs familar, easy vs hard to understand, etc)
2. How has you undertanding of these changed during this course.
3. Do you think you understand this article more now than you would have at the beginning of the semester
4. Write 3 questions and their answers that could be a quiz to see if someone understood or had misconceptions about the abstractions in this article.