The Language Reference & Guide
- Welcome to Emojicode
- Syntax
- The Basics
- Literals
- Variables and Assignment
- Control Flow
- Classes & Value Types
- Overloading
- Operators
- Optionals
- Errors
- Inheritance and Overriding
- Protocols
- Enumerations
- Types and Namespaces
- Types as Values
- Documentation
- Generics
- Callables
- Packages
- Threads
- Safe and Unsafe Code
- Memory Management
- References
- Appendix: The Emojicode Compiler
Threads
Emojicode offers concurrency, that is doing more than one thing at a time, and allows you to create threads, which can each independently execute code.
Creating Threads
Threads are represented by the 𧡠class of the s package. You can create a new thread by using the π initializer which accepts a callable which will be called on the newly created thread.
For example:
π𧡠π
π π€I execute on a different thread.π€
πβοΈ
If you wrapped the above into the π method compiled it into a program, you would possibly not see any output. The problem is, that the thread is created and the main thread, on which the π method was called, would continue to execute and would finally reach the end of the program. The program would likely terminate before the second thread had the chance to do anything.
In order to avoid this, you can wait for another thread to terminate with the help of the π method. If the thread has already finished the π will immediately return. The example below creates 5 threads (creating one thread and waiting for it doesn't make much sense) and then waits for each to finish.
π π
ππ¨ππ§΅πβοΈ β‘οΈ ππthreads
π i πβ© 0 5βοΈ π
π» threads π𧡠π ππ₯‘
π π€On a dark desert highway, cool wind in my hairπ€βοΈ
π π€Warm smell of colitas, rising up through the airπ€βοΈ
π π€Up ahead in the distance, I saw a shimmering lightπ€βοΈ
πβοΈβοΈ
π
π thread threads π
π threadβοΈ
π
π
The output of running the above code is similar to this:
On a dark desert highway, cool wind in my hairOn a dark desert highway, cool wind in my hairOn a dark desert highway, cool wind in my hairOn a dark desert highway, cool wind in my hair
On a dark desert highway, cool wind in my hair
Warm smell of colitas, rising up through the airWarm smell of colitas, rising up through the airWarm smell of colitas, rising up through the airWarm smell of colitas, rising up through the air
Warm smell of colitas, rising up through the air
Up ahead in the distance, I saw a shimmering lightUp ahead in the distance, I saw a shimmering lightUp ahead in the distance, I saw a shimmering lightUp ahead in the distance, I saw a shimmering light
Up ahead in the distance, I saw a shimmering light
The output is messed up because all threads are trying to execute simultaneously. The order in which a thread will get the opportunity to actually print something depends on your hardware as well as many other factors, like load factor of the computer.
Race Conditions and Mutexes
Imagine the following program:
π π¦ π
ππ account π’
π π
300 β‘οΈ πaccount
π
βοΈ πΈ sum π’ π
account β¬
οΈβ sum
π
βοΈ πΆ β‘οΈ π’ π
β©οΈ account
π
π
π π
ππ¨ππ§΅πβοΈ β‘οΈ ππthreads
ππ¦βοΈ β‘οΈ account
π i πβ© 0 10βοΈ π
π» threads π𧡠π ππ₯‘
π j πβ© 0 5βοΈ π
βͺοΈ πΆ accountβοΈ βΆοΈπ 10 π
π π€Money, money, money β Must be funnyπ€βοΈ
πΈ account 10βοΈ
π
π
πβοΈβοΈ
π
π thread threads π
π threadβοΈ
π
π π‘ πΆ accountβοΈ 10βοΈβοΈ π Print the balance
π
It creates a bank account with an initial credit balance of 300β¬. Then 10 threads are created which each try to withdraw 10β¬ 5 times if there is money left. You might now expect that the balance will be 0β¬ in the end because the threads only tried to get more money when available but never overdraw the account. Letβs try.
...
Money, money, money β Must be funny
-70
Strange, letβs try again.
...
Money, money, money β Must be funny
-90
You probably already know what happened. What we experience here is called a race condition. Letβs analyze this part of our code again:
βͺοΈ πΆ accountβοΈ βΆοΈπ 10 π π Thereβs money left
π π€Money, money, money β Must be funnyπ€βοΈ
πΈ account 10βοΈ
π
Imagine the following situation: A thread comes and sees that exactly 10β¬ are left. So the body of the βͺοΈ is entered and the thread prints a message. In exactly this moment another thread comes along, checks the balance and also sees there are 10β¬ left and enters the body of the βͺοΈ. The former thread now moves on to withdraw 10β¬ as the second one will do after it has printed a message. So they withdrew 20β¬! In reality the program is even faster and all threads execute the same piece of code at virtually the same time.
Now, how can we fix this? The solution is to use an instance of π, which is also called a mutex. A mutex ensures that only ever one thread can access a data structure or run a piece of code.
Weβve reworked our example to use a mutex:
π π
ππ¨ππ§΅πβοΈ β‘οΈ ππthreads
ππ¦βοΈ β‘οΈ account
ππβοΈ β‘οΈ mutex
π i πβ© 0 10βοΈ π
π» threads π𧡠π ππ₯‘
π j πβ© 0 5βοΈ π
π mutexβοΈ
βͺοΈ πΆ accountβοΈ βΆοΈπ 10 π
π π€Money, money, money β Must be funnyπ€βοΈ
πΈ account 10βοΈ
π
π mutexβοΈ
π
πβοΈβοΈ
π
π thread threads π
π threadβοΈ
π
π π‘ πΆ accountβοΈ 10βοΈβοΈ π Print the balance
π
If a thread comes to the line π mutexβοΈ
it will try to lock the mutex. If the mutex is not already locked, that is if no other thread has already passed this line, the thread will be able to do this and will continue. Otherwise however, the thread will wait until it itself can lock the mutex. The thread which grabbed the mutex unlocks the mutex at the end of the critical part by calling π mutexβοΈ
. At this point another thread can get the chance to lock the mutex β which thread however depends on your hardware, operating system, etc.
An operation like this which is protected from disturbances by other threads is called atomic.
And now, no matter how often you try, you will always get the expected result:
...
Money, money, money β Must be funny
Money, money, money β Must be funny
0
Atomicity of the s Package
Itβs important to note that none of the classes in the s package guarantee atomicity. If you access an s package data structures always make sure to use a mutex to avoid race conditions.