why synchronized object can still be manipulated - multithreading

Code snippet like below:
List<String> list = new ArrayList<>();
public void addValue(int i) {
synchronized (list) {
list.add("list" + i);
}
}
My question is that what is locked by keyword synchronized.
What will be checked of the list when two threads are asking to execute the code block?
The same question is that I synchronized this but its fields can still be changed.

The synchronized block is locked. When the code runs, a thread does not lock the object, instead, it OBTAINS the lock of the list object,(which is a mark word inside the object header) so other thread cannot obtain the same lock. As a result, the code inside the block can only be executed by one thread at the same time.

Related

Ehcache concurrent read and write from multiple threads

I am having an issue with access to Ehcache when Thread1 puts a new key/value into the cache and the Thread2 tries to read it. Read by Thread2 doesn't return the value inserted by Thread1.
Note that first method is invoked by starting the application and the second one is invoked almost at the same time by a REST controller. Also in the example below I am using BlockingCache but it was also tested with a simple cache. Explicit locking was also tested.
It looks like so:
private void processThread1(Object object) {
BlockingCache blockingCache = new BlockingCache(getCache());
blockingCache.put(new Element(object.getKey(), object));
}
private void processThread2(Object object) {
BlockingCache blockingCache = new BlockingCache(getCache());
// this value is not updated by processThread1(..) when
// it's accessed, although processThread1(..) method call
// finishes before this method is called
SomeObject someObject = blockingCache.get(object.getKey());
}
Cache getCache() {
return cacheManager.getCache(cacheName);
}

C# Thread.Start life cycle

I have a question about the lifecycle of a thread when i use Thread.Start, for example if a do a foreach loop like this one:
foreach(var item in MyList)
{
var t = new Thread(ProcessRequest);
t.Start(item);
}
private void ProcessRequest(ListItem item)
{
//do something
}
In this case it will exists N Threads, so what is the lifecycle of all these?
I will appreciate your explanation
Each thread exists until it's ProcessRequest is finished. Once the method returns the thread is returned to the threadpool to be used again.
Even though you are not maintaining a reference to the thread object it's referenced by the framework and the OS so it won't get freed up until the thread is finished running at a minimum.

Hibernate. Entity created in main thread isn't visible from child one

I found strange hibernate behavior and I cannot explain it.
If I create an object in default thread inside transaction and make manual flush
then I cannot find it in other thread.
If I create an object in one special thread with the same conditions then everything is all right.
Here is the code that I described above:
// transaction template with propagation required
ttNew.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
Assert.assertEquals(envStDao.getAll().size(), 0);
g = new Group();
g.setDescription("trial");
// in debugger I get id = 1
groupDao.save(g);
groupDao.flush();
accDao.flush();
}
});
// second stage right after the first - searching the group
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
ttNew.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
// here I get NULL!
Group gg = groupDao.get(1);
}
});
}
});
t2.start();
t2.join();
If I wrap first block of the code into thread just as former I get the group.
Are any ideas?
I run above code in junit test. Dao objects use HibernateTemplate.
Due to transaction isolation you cannot see uncommitted data in another transaction. you have two different transaction here , so one cannot see uncommitted data of another.
The default isolationist is read committed. flush dosnt mean commit. commit will be done only at the end of the transaction. so when you flush the data in first transaction the data is written to the db , but doesn’t commit, so transaction 2 cannot see it.

Lock() not effective

I'm trying to lock an object whiel itterating through its elements. The arraylist allThreads of mine is really not locked, because during the execution of the "foreach" I get a exception saying "Collection was modified; enumeration operation may not execute." I thought that was the whole deal with lock?
lock (mApp.allThreads)
{
foreach (Thread t in mApp.allThreads)
if (t.Name == "OpcDAWriter" && t != Thread.CurrentThread)
t.Join();
}
I think you might have misunderstood what lock does for you. It does not prevent other code from manipulating the object that you have taken a lock on. What it does is to prevent one thread from acquiring a long on one object, while another thread is holding the lock.
If you want to prevent one thread from manipulating the collection while another thread is iterating over it, you will need to put both the iterating code, and the manipulating code within lock blocks, locking on the same object.
Simple sample:
class LockDemo
{
private IList<string> _items;
private object _lock = new object();
public LockDemo()
{
_items = new List<string>(new[] { "one", "two", "three" });
}
public void RemoveItem(string item)
{
lock (_lock)
{
_items.Remove(item);
}
}
public void DoSomethingThatIteratesOverTheList()
{
lock (_lock)
{
foreach (var item in _items)
{
// do something with item
}
}
}
}
Notice how all access to the list (except for the constructor in this case) are wrapped in lock blocks that are all locking on the same object. Also note that this object is not the list itself, but an object that is used only for locking purposes. This shows that lock does not lock the object as such, but provides a mechanism to control what parts of the code that may or may not be executed in parallel by different threads.
You are joining into the t thread, so it probably gets removed from mApp.allThreads or something else happens due to the join, thus modifying the collection.
Also, just because you are looking the object, not all other methods could lock on it, the lock only works when all methods accesing the object are locking on it. You could try using an external object as your lock parameter, ie:
private readonly _lock = new object();
[...]
lock(_lock)
{
foreach....
}
but I doubt that will change anything.

Do C# 4.0 BCL SpinLock's spin/block when they can't get a lock?

Given the following code:
...
private static SpinLock logLock = new SpinLock(false);
...
private static void ThreadFunc()
{
bool lockTaken = false;
logLock.Enter(ref lockTaken)
{
try
{
// do stuff with during an acquired SpinLock
}
finally
{
logLock.Exit();
}
}
}
If the Enter block "fails" because it receives a false on the lock being acquired, does the current thread spin like a spinlock and wait until it can acquire it or is this block simply bypassed and that thread loses out ?
Thanks,
Scott
A SpinLock by definition causes the thread to spin while waiting to acquire for a lock rather than blocking. Enter does not "fail" if it can't acquire the lock, it just waits.
The only case where Enter may fail throwing an exception is when thread ownership is activated, using either new SpinLock() or new SpinLock(true). In this case an exception is thrown when a thread tries to acquire a lock it already owns. In your case this can never happen because you created the lock with tracking disabled (SpinLock(false)). If the thread tries to re-acquire the lock it will simply deadlock.
This is described in the documentation of the SpinLock.Enter method.
A SpinLock is basically just a loop around trying to set a variable to a specific value.
You could consider its implementation as follows:
public struct SpinLock
{
private volatile bool _Locked;
public void Acquire()
{
while (_Locked)
;
_Locked = true;
}
public void Release()
{
_Locked = false;
}
}
(of course, the above code is not thread-safe, and I know that's not the signature of the methods of the class, it's just a pseudo-code variant to show what it is doing)
So yes, if the SpinLock is already in a locked state, attempting to acquire it will spin until it becomes available.
Also, note that by default (as in your example), the struct does not keep track of who owns the lock. This means that if a thread tries to acquire the lock twice, it will deadlock with itself on the second attempt.
The purpose of SpinLock is to be a user-level lock with little overhead. It does not add GC pressure, nor does it allocate any kernel synchronization object, it's just a struct with a few fields.

Resources