|
Back in the day, I wrote operating systems, and thread safety was an issue (although I don't think we called it that at the time). Here's a VERY simplistic example of what might happen. Let's say you had a language that compiled an IF statement this way: IF BYTE1 = BYTE2 THEN GOTO EQUAL ----- 001: CALL JUMPEQUAL(@BYTE1, @BYTE2, @EQUAL) 101: JUMPEQUAL: 102: MOV *PARM1, A // Get value pointed to by Parm 1 into register A 103: MOV *PARM2, B // Get value pointed to by Parm 2 into register B 104: CMP A, B // Compare them 105: JMPEQ *PARM3 // Jump to address in Parm 3 if equal Pretty simple stuff. Load the memory values into registers, compare them, and jump to the instruction if equal. The problem with threads is that one thread can interrupt the execution of another thread at any time and run the same code (this is called reentrancy). So, in this case, let's say the first thread is executing and byte1 and byte2 are equal. It should jump to EQUAL, right? But if a second thread comes through and interrupts thread one between instructions 103 and 104 and puts DIFFERENT values into registers A and B, they might no longer be equal. And unless the interrupting thread restores the state of all the registers, the results are unpredicted when you return control to thread one. And this saving and restoring of state is essentially the difference between a task (or job) and a thread. Saving and restoring state can be a very costly operation, and threads are designed to be lightweight, thus they don't do the state save/restore. And so unless you have a way of preventing one thread from interrupting another at a crucial point in the code, you can have this sort of problem. In the olden days, we would actually disable interrupts during sections of code that were vulnerable. That's okay when you own the CPU, but these days it's a bit more complicated, and you need to "synchronize" the method, which cause it to lock something (this something is called a semaphore or mutex) while the vulnerable code is executed. That way, two threads can't walk over each other. Non-thread-safe code is code that cannot handle reentrancy. These days, it's not so much about registers as in my Assembly Language 101 example above; I'm pretty sure that level of state swapping is handled by the CPU (although ask me about LPAR and L2 cache some day). Instead, it's the use of temporary work variables that causes problems (in Java, for example, instance variables in servlets are not threadsafe). It takes a lot of work to make code truly reentrant, and it is especially difficult to back engineer reentrancy into code originally written without it, which is probably a big reason why RPG is not threadsafe without activation groups. Joe
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2025 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.