I have a delphi7 program with two threads. If I alloc memory in the first thread using new(), can I release it with dispose in the other thread ? I also am using fastMM
Yes. Dynamic memory is shared between all threads in the process.
You must make sure that the IsMultiThread global variable is set True at an early stage. Using TThread or BeginThread to create threads will set IsMultiThread to True. If you know that your code uses threads then you may as well set IsMultiThread to True explicitly during initialization.
Obviously the allocation must complete before you start the deallocation.
Yes, all memory of the current process is accessible to all threads. But you should absolutely make sure that these calls are not made simultaneously or do not take place in the wrong order, because that is easily done with multiple threads whose execution time is unpredictable.
Related
So I'm trying to use mutex_init(), mutex_lock(), mutex_unlock() for thread synchronization.
I am currently trying to schedule threads in a round robin fashion(but more than 1 thread could be running at a time) and I set the current state of a thread to TASK_INTERRUPTIBLE, followed by waking up another thread whose PID, I have in a list.
I need to iterate over this list for my logic.
As I understand it, I need to lock this list as I access its elements, or another thread might miss a new entry while I'm making changes to it. Also, as one mutex has locked a resource, no other mutex can unlock it, until the original mutex releases it.
But, I'm still not sure if I'm locking it correctly. (I release the lock before I call schedule(), and re-lock after that)
I declare a mutex locally within a thread and lock the list. After my current thread locks
mutex_lock(&lock);
and I iterate over the list, till I find something(or ends if it doesn't find anything), then unlocks.
mutex_unlock(&lock);
I assume locking while I iterate is legal. I have never seen examples of this though.
Also, is it normal for the process to have a state of (TASK_UNINTERRUPTIBLE) while it holds a mutex lock?
EDIT : I am adding some more information based on the answer below.
It is possible my program may be run on a virtual machine with a single core. Therefore, I do not want to risk infinite polling using spin_lock().
I am trying to maintain scheduling between threads that have a certain id. For example if there are 4 threads. 2 in set 'A' and 2 in set 'B'. I allow only 1 thread to run in each set. But I switch between threads in a given set. However, a thread in set 'A' should not switch to any thread in set 'B'
(I know the kernel scheduler wont be perfect, so an approximate switching will do).
My Reasoning for TASK_STATE's:
1) Initial thread that gets created is running.
2) If another thread in the same set is running (and this one hasn't executed for a given time). Set other thread to TASK_INTERRUPTIPLE, while calling schedule(); Note: There can be more than 2 threads in each set, but let's keep it simple by considering only 2 for now.
3) If it has executed for enough time, set this task to TASK_INTERRUPTIPLE, set the other task in the same set to TASK_RUNNING, while calling schedule();
All this logic happens while I am accessing certain data structures which are locked by a (now) Global Mutex. I unlock the mutex just before I call schedule(), and instantly re-lock afterward. After my logic part is done, I completely unlock the mutex.
Is there anything fundamentally wrong with the approach?
As I understand it, I need to lock this list as I access its elements
Yes, that is true. But if you use a mutex, you're going to be really sad because a call to lock/unlock is a call to the scheduler. Therefore, calling it from inside the scheduler should result in deadlock. What you need to do depends on if your processor is multi-core or (the mythical) single-core. (Is this a virtual system?) On a single-core processor you can disable interrupts. On a multi-core processor, disabling interrupts is not sufficient (it only disables interrupts for that one core, and another core may still be interrupted). The simplest thing to do on a multi-core is to use a spinlock. Unlike the mutex, both of these locking mechanisms can be unlocked from different threads.
I set the current state of a thread to TASK_INTERRUPTIBLE
Is the thread being taken off the CPU? If so, it's not running, so I suspect that TASK_INTERRUPTIBLE is the wrong state. It would be helpful if you could list the possible states for me or if you could describe what the state is supposed to indicate. Because to me "TASK_INTERRUPTIBLE" sounds like a running task.
I declare a mutex locally within a thread and lock the list
Local mutexes are a red flag! The resource you are locking should be protected by a mutex with the same scope. If the list is global, it should have a global mutex to protect it. Threads that want to use the list must first acquire its mutex. Of course, as I already talked about, you probably want to use a different kind of locking to protect the list of ready-to-run processes.
I assume locking while I iterate is legal
It is perfectly legal (assuming of course that your mutual exclusion scheme is bug-free). In fact, it's required. If another thread were allowed to, for example, remove a node from the list while you were reading it, you could end up dereferencing a deleted node.
Also, is it normal for the process to have a state of TASK_UNINTERRUPTIBLE while it holds a mutex lock?
No, not while it holds the lock if the process is currently running on a CPU. A mutex is available to user code. If holding a mutex made the process uninterruptible, that would mean that a process could hijack the system by simply locking a mutex and never releasing it. Now, you will find that the lock and unlock functions need to be uninterruptible on a single-core processor. However, it doesn't make sense to set the state for the process because it's actually the scheduler that must not be interrupted.
Imagine I have a BackgroundWorker that operates on a WorkObject shared between a main thread and the worker thread.
The WorkObject contains a boolean value "IsFinished". When the BackgroundWorker finishes its work, it sets IsFinished to true.
The main thread can periodically check IsFinished to see if the worker is done.
Is it necessary to use a synchronization mechanism to protect access to IsFinished in such a simple case like this? Is it possible for the mainthread and worker to try to access IsFinished in exactly the same cycle and cause some sort of weird glitch?
If
You only have one writer; AND
You do not care about false negatives (ie. isFinished appears false to the main thread while it is true to the worker thread)
Then you could get away without having synchronization.
Is it possible for the mainthread and worker to try to access IsFinished in exactly the same cycle and cause some sort of weird glitch?
No. Normal computer hardware serializes all memory accesses.
Is it necessary to use a synchronization mechanism ... in such a simple case?
user2244003's answer mentioned "false negatives."
Most modern workstation and server systems, and even many mobile systems these days, have two or more CPUs, each of which has its own memory cache. When one thread writes the isFinished variable, a number of things have to happen before another thread can see the change. Exactly when those things happen can be different on different hardware platforms, in different operating systems and, in different implementations of your programming language's run-time support system.
In some programming languages/libraries there is a very clear specification of how the memory system must behave. In others (e.g., in C++ prior to C++11) you were pretty much on your own to discover what worked and what didn't work. (Including what worked and what didn't work for your customers, which could be different from what worked or not for you.)
Primitives that force memory updates to become visible to the threads that need to see them are called memory barriers.
Different languages/libraries have different ways of letting you specify memory barriers, but this rule of thumb works in most of them: Whatever thread A writes to memory before it unlocks some lock L will be visible to thread B after thread B locks the same lock L.
Your language or library might also support some kind of atomic data type for which every access has implied memory barriers.
As I got to know that apart from data segment and code segment threads also share heap segment
What resources are shared between threads??
then if I create a variable dynamically using malloc() or calloc() inside the thread then does that variable would be accessible to all the other threads of the same process?
Theoretically, if you know the memory address. Yes, heap allocated variables should be accessible from any thread within the same process.
{malloc, calloc, realloc, free, posix_memalign} of glibc-2.2+ are thread safe
http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2005-07/0323.html
Original post
Generally, malloc/new/free/delete on multi threaded systems are thread safe, so this should be no problem - and allocating in one thread , deallocating in another is a quite common thing to do.
As threads are an implementation feature, it certainly is implementation dependant though - e.g. some systems require you to link with a multi threaded runtime library.
And this
Besides also answered in: the link you posted
Threads differ from traditional multitasking operating system
processes in that:
processes are typically independent, while threads exist as subsets of
a process processes carry considerable state information, whereas
multiple threads within a process share state as well as memory and
other resources processes have separate address spaces, whereas
threads share their address space processes interact only through
system-provided inter-process communication mechanisms. Context
switching between threads in the same process is typically faster than
context switching between processes.
So, yes it is.
Example:
A thread finishes writing to a shared variable, and then it unlocks it, but continues to use that variable's value (without changing it).
And immediately, another thread successfully unlocks() that mutex and reads the shared variable.
For my (mis-)understanding, some things could be happening on this situation:
On the WRITER thread:
A compiler optimization could make the write occur only at some later point
The written value could be retained in the current CPU core's cache, and flushed to the memory at some later point
On the READER thread:
The value of the variable may have been read before the mutex lock(), and because of some compiler optimization or just the usual work of the CPU cache, still be considered "already read from memory" and thus, not fetched from the memory again.
Thus, the value we have here is not the updated one from the other thread.
Does the pthread mutex lock/unlock() functions execute any code to "flush" the current cache to the memory and anything else needed to make sure the current thread is synchronized with everything else (I cannot think of anything else than the cache), or is it just not needed (at least in all known architectures)?
Because if all the mutexes do is just what the name does - mutual exclusion to it's reference - then, if I have thousands of threads dealing with the same data and from my algorithm's point of view, I already know that when one thread is using a variable, no other thread will try to use it at the same time, than it means I don't need a mutex? Or will my code be missing some low level and architecture-specific method(s) implemented inside the PTHREAD library to avoid the problems above?
The pthreads mutex lock and unlock functions are among the list of functions in POSIX "...that synchronize thread execution and also synchronize memory with respect to other threads". So yes, they do more than just interlock execution.
Whether or not they need to issue additional instructions to the hardware is of course architecture dependent (noting that almost every modern CPU architecture will at least happily reorder reads with respect to each other unless told otherwise), but in every case those functions must act as "compiler barriers" - that is, they ensure that the compiler won't reorder, coalesce or omit memory accesses in situations where it would otherwise be allowed to.
It is allowed to have multiple threads reading a shared value without mutual exclusion though - all you need to ensure is that both the writing and reading threads executed some synchronising function between the write and the read. For example, an allowable situation is to have many reading threads that defer reading the shared state until they have passed a barrier (pthread_barrier_wait()) and a writing thread that performs all its writes to the shared state before it passes the barrier. Reader-writer locks (pthread_rwlock_*) are also built around this idea.
I have multiple threads that are accessing the same data and it is too painful to make them thread safe. Therefore, they are now forced to run only on one CPU core using CPU affinity and only one thread can be running at the same time.
I was wondering if it is possible to group these threads and let them float to other CPU cores all together ? In this way, I don't have to spare one CPU core for these threads.
This is based on Unix/BSD platform
There is no way to do this on Windows. I don't know about Unix/Linux but I doubt it's possible.
Note, that this does not make your system thread-safe. Even on uni-processor machines thread-safety is a concern.
i++
is not atomic. Two thread can both read i, then compute i+1, then write i. That results in a lost update.
You need to throw this approach away. Probably, you should be using a global lock that you hold around accesses to shared mutable state. That makes all these concerns go away and is reasonably simple to implement.
Either make the code thread safe or use just one thread.
The simplest solution is probably the "one big lock" model. With this model, one lock protects all the data that's shared among the threads and not handled in a thread-safe way. The threads start out always holding the lock. Then you identify all the points where the threads can block and release the lock during that block.