WaitOne() timeout parameter lost? - dot42

why System.Threading.WaitHandle.WaitOne() hasn't overload for the timeout parameters as available in standard .NET implementation: http://msdn.microsoft.com/en-us/library/cc189907(v=vs.110).aspx
It's very useful in working threads when, during thread sleep, thread is requested to stop from Main UI thread.. Other ways to implement it?
Example:
public void StartBatteryAnimation()
{
whStopThread = new ManualResetEvent(false);
batteryAnimationThread = new Thread(new ThreadStart(BatteryAnimation_Callback));
batteryAnimationThread.Start();
}
public void StopBatteryAnimation()
{
whStopThread.Set();
batteryAnimationThread.Join();
batteryAnimationThread = null;
whStopThread.Dispose();
whStopThread = null;
}
public void BatteryAnimation_Callback()
{
bool exitResult = false;
while (true)
{
// Do some stuff
exitResult = whStopThread.WaitOne(WAIT_INTERVALL);
if (exitResult) break;
}
}
Thanks Frank for your (1000th!!) reply.
So my custom implementation for WaitHandle.WaitOne(int Timeout) has been:
private Thread batteryAnimationThread = null;
private Semaphore batteryAnimationSemaphore = null;
public void StartBatteryAnimation()
{
batteryAnimationSemaphore = new Semaphore(1);
batteryAnimationSemaphore.Acquire();
batteryAnimationThread = new Thread(new ThreadStart(BatteryAnimation_Callback));
batteryAnimationThread.Start();
}
public void StopBatteryAnimation()
{
batteryAnimationSemaphore.Release();
batteryAnimationThread.Join();
batteryAnimationThread = null;
batteryAnimationSemaphore = null;
}
public void BatteryAnimation_Callback()
{
bool stopThread = false;
try
{
while (true)
{
// Do some stuff..
stopThread = batteryAnimationSemaphore.TryAcquire(1, BATTERY_ANIMATION_INTERVALL, Java.Util.Concurrent.TimeUnit.MILLISECONDS);
if (stopThread) break;
}
catch (Exception ex)
{
}
batteryAnimationSemaphore.Release();
}
Is this the right way for?
Thanks

This one hasn't been implemented yet. You may use semaphore.tryAcquire instead.
Background: Due to its design, dot42 supports the entire Android API (C# classes are proxies and generated from the android.jar). But is supports only part of the .NET API because the .NET classes are handcrafted on top of the Android/Java API.
Related question: Java Equivalent of .NET's ManualResetEvent and WaitHandle
UPDATE
We released the API under Apache License 2.0 so anyone may contribute now. I also logged an issue.

Related

How to properly manage messages sent to a thread in C++

In my Android app, I use C++ to do some work. In my C++ code, I use a thread to do some tasks. Using this example and this example, here is how I proceed (I simplified the actual code to keep it easy to read):
std::thread* threadLocal;
std::queue<ThreadMessage*> queueLocale;
std::mutex mutexLocal;
std::condition_variable cvLocal;
struct ThreadMessage
{
ThreadMessage(int i)
{
id = i;
}
int id;
};
void MyWorkerThread::createThread()
{
if (!threadLocal)
{
threadLocal = new std::thread(&MyWorkerThread::process, this);
}
}
void MyWorkerThread::sendTask1()
{
if (threadLocal)
{
// message:
ThreadMessage* threadMessage = new ThreadMessage(MSG_TASK_1);
// send the message:
std::unique_lock<std::mutex> lock(mutexLocal);
queueLocale.push(std::move(threadMessage));
cvLocal.notify_one();
}
}
void MyWorkerThread::sendTask2()
{
if (threadLocal)
{
// message:
ThreadMessage* threadMessage = new ThreadMessage(MSG_TASK_2);
// send the message:
std::unique_lock<std::mutex> lock(mutexLocal);
queueLocale.push(std::move(threadMessage));
cvLocal.notify_one();
}
}
void MyWorkerThread::process()
{
while (1)
{
// init :
ThreadMessage* threadMessage = 0;
// waiting for messages :
{
std::unique_lock<std::mutex> lock(mutexLocal);
while (queueLocale.empty())
{
cvLocal.wait(lock);
}
threadMessage = std::move(queueLocale.front());
queueLocale.pop();
}
// tasks :
switch (threadMessage->id)
{
case MSG_TASK_1:
{
doSomeWork1();
delete threadMessage;
break;
}
case MSG_TASK_2:
{
doSomeWork2();
delete threadMessage;
break;
}
default:
{
delete threadMessage;
break;
}
}
}
}
It works well in most cases, but sometimes, my app crashes when a delete threadMessage is called, and I don't understand why (since I don't see how it can be called twice on a same object).
Here are the reasons why I need to send messages to a thread, instead of just creating new threads each time I want to run doSomeWork1() or doSomeWork2():
The doSomeWork1() and doSomeWork2() functions have to be executed in the same thread
One of those functions is very frequently called (approx. 200 times / sec), so I don't want to create a thread each time
So my question is: what is the proper way to send a message to a thread, and manage it inside the thread, to avoid error on the delete?
Thanks for your help.

gRPC and etcd client

This question involves etcd specific stuff, but I think the question more related to work with gRPC in general.
I'm trying to create etcd Watch for some keys, since the documentation is sparse I had a look at Nokia implementation
It was easy to adapt code to my needs and I came up with first version which worked just fine, creating WatchCreateRequest, and firing callback on key update. So far so good. Then I've tried to add more than one key to watch. Fiasco! ClientAsyncReaderWriter is failing to Read/Write in such a case. Now to the question.
If I have following members in my class
Watch::Stub watchStub;
CompletionQueue completionQueue;
ClientContext context;
std::unique_ptr<ClientAsyncReaderWriter<WatchRequest, WatchResponse>> stream;
WatchResponse reply;
and I want to support multiple Watches added to my class, I guess I have to hold several variables per watch and not as class members.
First of all, I guess, WatchResponse reply should be one per Watch. I'm less sure about the stream, should I hold one per Watch? I'm almost sure that context could be reused for all Watches and 100% sure the stub and completionQueue can be reused for all Watches.
So the question is my guess-work right? Whats about thread safety? Didnt find any documentation describing what objects are safe to use from multiple thread and where I have to synchronize access.
Any link to documentation (not this one) will be appreciated!
Test code before I split members into single Watch property
(no proper shutdown, I know)
using namespace grpc;
class Watcher
{
public:
using Callback = std::function<void(const std::string&, const std::string&)>;
Watcher(std::shared_ptr<Channel> channel) : watchStub(channel)
{
stream = watchStub.AsyncWatch(&context, &completionQueue, (void*) "create");
eventPoller = std::thread([this]() { WaitForEvent(); });
}
void AddWatch(const std::string& key, Callback callback)
{
AddWatch(key, callback, false);
}
void AddWatches(const std::string& key, Callback callback)
{
AddWatch(key, callback, true);
}
private:
void AddWatch(const std::string& key, Callback callback, bool isRecursive)
{
auto insertionResult = callbacks.emplace(key, callback);
if (!insertionResult.second) {
throw std::runtime_error("Event handle already exist.");
}
WatchRequest watch_req;
WatchCreateRequest watch_create_req;
watch_create_req.set_key(key);
if (isRecursive) {
watch_create_req.set_range_end(key + "\xFF");
}
watch_req.mutable_create_request()->CopyFrom(watch_create_req);
stream->Write(watch_req, (void*) insertionResult.first->first.c_str());
stream->Read(&reply, (void*) insertionResult.first->first.c_str());
}
void WaitForEvent()
{
void* got_tag;
bool ok = false;
while (completionQueue.Next(&got_tag, &ok)) {
if (ok == false) {
break;
}
if (got_tag == (void*) "writes done") {
// Signal shutdown
}
else if (got_tag == (void*) "create") {
}
else if (got_tag == (void*) "write") {
}
else {
auto tag = std::string(reinterpret_cast<char*>(got_tag));
auto findIt = callbacks.find(tag);
if (findIt == callbacks.end()) {
throw std::runtime_error("Key \"" + tag + "\"not found");
}
if (reply.events_size()) {
ParseResponse(findIt->second);
}
stream->Read(&reply, got_tag);
}
}
}
void ParseResponse(Callback& callback)
{
for (int i = 0; i < reply.events_size(); ++i) {
auto event = reply.events(i);
auto key = event.kv().key();
callback(event.kv().key(), event.kv().value());
}
}
Watch::Stub watchStub;
CompletionQueue completionQueue;
ClientContext context;
std::unique_ptr<ClientAsyncReaderWriter<WatchRequest, WatchResponse>> stream;
WatchResponse reply;
std::unordered_map<std::string, Callback> callbacks;
std::thread eventPoller;
};
I'm sorry that I'm not very sure about the proper Watch design here. It's not very clear to me whether you want to create a gRPC call for each Watch.
Anyway, each gRPC call will have its own ClientContext, ClientAsyncReaderWriter. But stub and CompletionQueue is not per-call thing.
As far as I know, there is no central place to find the thread-safe classes. You may want to read the API document to have a correct expectation.
When I was writing the async server load reporting service, the only place I add synchronization myself is around CompletionQueue, so that I don't en-queue new tags to the cq if it's shut down.

Native IIS7.5 Module not running

I've created a simple CHttpModule that adds a custom header to all requests:
#define _WINSOCKAPI_
#include <windows.h>
#include <sal.h>
#include <httpserv.h>
class AppendHeaderModule : public CHttpModule {
public:
REQUEST_NOTIFICATION_STATUS
OnBeginRequest(
IN IHttpContext * pHttpContext,
IN IHttpEventProvider * pProvider
)
{
UNREFERENCED_PARAMETER(pProvider);
PCSTR testHeaderName = "Foo";
PCSTR testHeader = "bar";
pHttpContext->GetResponse()->SetHeader(testHeaderName, testHeader, (USHORT)strlen(testHeader), true);
return RQ_NOTIFICATION_CONTINUE;
}
VOID Terminate() {
delete this;
}
AppendHeaderModule() { }
~AppendHeaderModule() { }
};
class AppendHeaderModuleFactory : public IHttpModuleFactory {
public:
HRESULT
GetHttpModule(
OUT CHttpModule ** ppModule,
IN IModuleAllocator * pAllocator
)
{
UNREFERENCED_PARAMETER(pAllocator);
AppendHeaderModule* pModule = new AppendHeaderModule;
if (!pModule) {
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
else {
*ppModule = pModule;
pModule = NULL;
return S_OK;
}
}
void Terminate() {
delete this;
}
};
HRESULT __stdcall
RegisterModule(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo * pModuleInfo,
IHttpServer * pGlobalInfo
)
{
UNREFERENCED_PARAMETER(dwServerVersion);
UNREFERENCED_PARAMETER(pGlobalInfo);
AppendHeaderModuleFactory* pModule = new AppendHeaderModuleFactory;
if (pModule == NULL)
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
return pModuleInfo->SetRequestNotifications(pModule, RQ_BEGIN_REQUEST, 0);
}
I've copied it to C:\Windows\System32\inetsrv, registered the module, and added it to the list. However, I'm not seeing the additional header in any of my requests. I created a similar managed module, installed it to the GAC, registered it, and it works fine. But this native module seems to do nothing. Is there another step required to get native modules to handle requests?
Also, I'm not sure if it matters, but the requests are being made to an ASP.NET site. Do native handlers not run for ASP.NET?
If the module is a 32-bit module you need to enable 32-bit applications in the application pool for your website. Go to the Application Pools, select the pool for your website, Advanced Settings and set "Enable 32-Bit Applications to TRUE.

Adding Scaletempo to a playbin with Vala

I'm having trouble trying to use scaletempo with a playbin in Vala. I've created the playbin, and then created a bin to store the additional plugins swapping out the default audio sink. The example below I grabbed from pyTranscribe and converted to Vala but the Element.link_many is causing an error and I'm not quite sure why.
Am I going about this the right way? Does anybody have any other suggestions?
/* SoundPlayerBackend.vala */
/* Modified code from Damien Radtke's site. http://damienradtke.org/ */
using Gst;
public class SoundPlayerBackend {
//Constants
const double PLAYBACK_RATE_MODIFIER = 2.0;
const int SEEK_SECONDS = 10;
// Method delegates for notifying SoundPlayer about certain events
protected delegate void NotifyEos();
protected delegate void NotifyError(string message);
// Pointer to our EOS delegate
protected NotifyEos on_eos;
// Pointer to our Error delegate
protected NotifyError on_error;
public static void main(string[] args){
var soundplayer = new SoundPlayerBackend();
Gst.init(ref args);
soundplayer.setUri("file:///home/codenomad/Desktop/player-project/hurricane.mp3");
soundplayer.play();
string stop = stdin.read_line ();
while (stop != "stop") {
if (stop == "pause") { soundplayer.pause(); }
else if (stop == "play") { soundplayer.play(); }
stop = stdin.read_line ();
}
}
// Read-only reference to the current sound object
public dynamic Element sound { get; private set; }
// Read-only "is playing" property
public bool is_playing { get; private set; default = false; }
// Read-only "rate" property
public double rate { get; private set; default = 1; }
public void setUri(string uri) {
// Make sure any existing allocated resources are freed
if (sound != null)
sound.set_state(Gst.State.NULL);
sound = ElementFactory.make("playbin2", "playbin");
sound.uri = uri;
var audiobin = new Bin("audioline");
var scaletempo = ElementFactory.make("scaletempo", "scaletempo");
var convert = ElementFactory.make("audioconvert", "convert");
var resample = ElementFactory.make("audioresample", "resample");
var audiosink = ElementFactory.make("autoaudiosink", "audiosink");
audiobin.add_many(scaletempo, convert, resample, audiosink);
//edited based on comment below
//Element.link_many(scaletempo, convert, resample, audiosink);
scaletempo.link_many(convert, resample, audiosink);
var pad = scaletempo.get_pad("sink");
audiobin.add_pad(new GhostPad("sink", pad));
sound.set_property("audio-sink", audiobin);
sound.get_bus().add_watch(on_event);
}
// Play the sound
public void play() {
sound.set_state(State.PLAYING);
print("Playing\n");
is_playing = true;
}
// Pause it
public void pause() {
sound.set_state(State.PAUSED);
is_playing = false;
print("Paused\n");
}
// Event bus, listens for events and responds accordingly
protected bool on_event(Gst.Bus bus, Message message) {
switch (message.type) {
case MessageType.ERROR:
GLib.Error err;
string debug;
sound.set_state(Gst.State.NULL);
is_playing = false;
message.parse_error(out err, out debug);
on_error(err.message);
break;
case MessageType.EOS:
sound.set_state(Gst.State.READY);
is_playing = false;
on_eos();
break;
default:
break;
}
return true;
}
}
I tried using the same code making everything static and received the same outcome/error below:
SoundPlayerBackend.vala:121.9-121.67: error: Access to instance member `Gst.Element.link_many' denied
Element.link_many(scaletempo, convert, resample, audiosink);
Thanks in advance!
That line should read
scaletempo.link_many(convert, resample, audiosink);

Good example of livelock?

I understand what livelock is, but I was wondering if anyone had a good code-based example of it? And by code-based, I do not mean "two people trying to get past each other in a corridor". If I read that again, I'll lose my lunch.
Here's a very simple Java example of livelock where a husband and wife are trying to eat soup, but only have one spoon between them. Each spouse is too polite, and will pass the spoon if the other has not yet eaten.
public class Livelock {
static class Spoon {
private Diner owner;
public Spoon(Diner d) { owner = d; }
public Diner getOwner() { return owner; }
public synchronized void setOwner(Diner d) { owner = d; }
public synchronized void use() {
System.out.printf("%s has eaten!", owner.name);
}
}
static class Diner {
private String name;
private boolean isHungry;
public Diner(String n) { name = n; isHungry = true; }
public String getName() { return name; }
public boolean isHungry() { return isHungry; }
public void eatWith(Spoon spoon, Diner spouse) {
while (isHungry) {
// Don't have the spoon, so wait patiently for spouse.
if (spoon.owner != this) {
try { Thread.sleep(1); }
catch(InterruptedException e) { continue; }
continue;
}
// If spouse is hungry, insist upon passing the spoon.
if (spouse.isHungry()) {
System.out.printf(
"%s: You eat first my darling %s!%n",
name, spouse.getName());
spoon.setOwner(spouse);
continue;
}
// Spouse wasn't hungry, so finally eat
spoon.use();
isHungry = false;
System.out.printf(
"%s: I am stuffed, my darling %s!%n",
name, spouse.getName());
spoon.setOwner(spouse);
}
}
}
public static void main(String[] args) {
final Diner husband = new Diner("Bob");
final Diner wife = new Diner("Alice");
final Spoon s = new Spoon(husband);
new Thread(new Runnable() {
public void run() { husband.eatWith(s, wife); }
}).start();
new Thread(new Runnable() {
public void run() { wife.eatWith(s, husband); }
}).start();
}
}
Run the program and you'll get:
Bob: You eat first my darling Alice!
Alice: You eat first my darling Bob!
Bob: You eat first my darling Alice!
Alice: You eat first my darling Bob!
Bob: You eat first my darling Alice!
Alice: You eat first my darling Bob!
...
This will go on forever if uninterrupted. This is a livelock because both Alice and Bob are repeatedly asking each other to go first in an infinite loop (hence live). In a deadlock situation, both Alice and Bob would simply be frozen waiting on each other to go first — they won't be doing anything except wait (hence dead).
Flippant comments aside, one example which is known to come up is in code which tries to detect and handle deadlock situations. If two threads detect a deadlock, and try to "step aside" for each other, without care they will end up being stuck in a loop always "stepping aside" and never managing to move forwards.
By "step aside" I mean that they would release the lock and attempt to let the other one acquire it. We might imagine the situation with two threads doing this (pseudocode):
// thread 1
getLocks12(lock1, lock2)
{
lock1.lock();
while (lock2.locked())
{
// attempt to step aside for the other thread
lock1.unlock();
wait();
lock1.lock();
}
lock2.lock();
}
// thread 2
getLocks21(lock1, lock2)
{
lock2.lock();
while (lock1.locked())
{
// attempt to step aside for the other thread
lock2.unlock();
wait();
lock2.lock();
}
lock1.lock();
}
Race conditions aside, what we have here is a situation where both threads, if they enter at the same time will end up running in the inner loop without proceeding. Obviously this is a simplified example. A naiive fix would be to put some kind of randomness in the amount of time the threads would wait.
The proper fix is to always respect the lock heirarchy. Pick an order in which you acquire the locks and stick to that. For example if both threads always acquire lock1 before lock2, then there is no possibility of deadlock.
As there is no answer marked as accepted answer, I have attempted to create live lock example;
Original program was written by me in Apr 2012 to learn various concept of multithreading. This time I have modified it to create deadlock, race condition, livelock etc.
So let's understand the problem statement first;
Cookie Maker Problem
There are some ingredient containers: ChocoPowederContainer, WheatPowderContainer. CookieMaker takes some amount of powder from ingredient containers to bake a Cookie. If a cookie maker finds a container empty it checks for another container to save time. And waits until Filler fills the required container. There is a Filler who checks container on regular interval and fills some quantity if a container needs it.
Please check the complete code on github;
Let me explain you implementation in brief.
I start Filler as daemon thread. So it'll keep filling containers on regular interval. To fill a container first it locks the container -> check if it needs some powder -> fills it -> signal all makers who are waiting for it -> unlock container.
I create CookieMaker and set that it can bake up to 8 cookies in parallel. And I start 8 threads to bake cookies.
Each maker thread creates 2 callable sub-thread to take powder from containers.
sub-thread takes a lock on a container and check if it has enough powder. If not, wait for some time. Once Filler fills the container, it takes the powder, and unlock the container.
Now it completes other activities like: making mixture and baking etc.
Let's have a look in the code:
CookieMaker.java
private Integer getMaterial(final Ingredient ingredient) throws Exception{
:
container.lock();
while (!container.getIngredient(quantity)) {
container.empty.await(1000, TimeUnit.MILLISECONDS);
//Thread.sleep(500); //For deadlock
}
container.unlock();
:
}
IngredientContainer.java
public boolean getIngredient(int n) throws Exception {
:
lock();
if (quantityHeld >= n) {
TimeUnit.SECONDS.sleep(2);
quantityHeld -= n;
unlock();
return true;
}
unlock();
return false;
}
Everything runs fine until Filler is filling the containers. But if I forget to start the filler, or filler goes on unexpected leave, sub-threads keep changing their states to allow other maker to go and check the container.
I have also create a daemon ThreadTracer which keeps watch on thread states and deadlocks. This the output from console;
2016-09-12 21:31:45.065 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:RUNNABLE, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]
2016-09-12 21:31:45.065 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]
WheatPowder Container has 0 only.
2016-09-12 21:31:45.082 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:RUNNABLE]
2016-09-12 21:31:45.082 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]
You'll notice that sub-threads and changing their states and waiting.
A real (albeit without exact code) example is two competing processes live locking in an attempt to correct for a SQL server deadlock, with each process using the same wait-retry algorithm for retrying. While it's the luck of timing, I have seen this happen on separate machines with similar performance characteristics in response to a message added to an EMS topic (e.g. saving an update of a single object graph more than once), and not being able to control the lock order.
A good solution in this case would be to have competing consumers (prevent duplicate processing as high up in the chain as possible by partitioning the work on unrelated objects).
A less desirable (ok, dirty-hack) solution is to break the timing bad luck (kind of force differences in processing) in advance or break it after deadlock by using different algorithms or some element of randomness. This could still have issues because its possible the lock taking order is "sticky" for each process, and this takes a certain minimum of time not accounted for in the wait-retry.
Yet another solution (at least for SQL Server) is to try a different isolation level (e.g. snapshot).
I coded up the example of 2 persons passing in a corridor. The two threads will avoid each other as soon as they realise their directions are the same.
public class LiveLock {
public static void main(String[] args) throws InterruptedException {
Object left = new Object();
Object right = new Object();
Pedestrian one = new Pedestrian(left, right, 0); //one's left is one's left
Pedestrian two = new Pedestrian(right, left, 1); //one's left is two's right, so have to swap order
one.setOther(two);
two.setOther(one);
one.start();
two.start();
}
}
class Pedestrian extends Thread {
private Object l;
private Object r;
private Pedestrian other;
private Object current;
Pedestrian (Object left, Object right, int firstDirection) {
l = left;
r = right;
if (firstDirection==0) {
current = l;
}
else {
current = r;
}
}
void setOther(Pedestrian otherP) {
other = otherP;
}
Object getDirection() {
return current;
}
Object getOppositeDirection() {
if (current.equals(l)) {
return r;
}
else {
return l;
}
}
void switchDirection() throws InterruptedException {
Thread.sleep(100);
current = getOppositeDirection();
System.out.println(Thread.currentThread().getName() + " is stepping aside.");
}
public void run() {
while (getDirection().equals(other.getDirection())) {
try {
switchDirection();
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
}
C# version of jelbourn's code:
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace LiveLockExample
{
static class Program
{
public static void Main(string[] args)
{
var husband = new Diner("Bob");
var wife = new Diner("Alice");
var s = new Spoon(husband);
Task.WaitAll(
Task.Run(() => husband.EatWith(s, wife)),
Task.Run(() => wife.EatWith(s, husband))
);
}
public class Spoon
{
public Spoon(Diner diner)
{
Owner = diner;
}
public Diner Owner { get; private set; }
[MethodImpl(MethodImplOptions.Synchronized)]
public void SetOwner(Diner d) { Owner = d; }
[MethodImpl(MethodImplOptions.Synchronized)]
public void Use()
{
Console.WriteLine("{0} has eaten!", Owner.Name);
}
}
public class Diner
{
public Diner(string n)
{
Name = n;
IsHungry = true;
}
public string Name { get; private set; }
private bool IsHungry { get; set; }
public void EatWith(Spoon spoon, Diner spouse)
{
while (IsHungry)
{
// Don't have the spoon, so wait patiently for spouse.
if (spoon.Owner != this)
{
try
{
Thread.Sleep(1);
}
catch (ThreadInterruptedException e)
{
}
continue;
}
// If spouse is hungry, insist upon passing the spoon.
if (spouse.IsHungry)
{
Console.WriteLine("{0}: You eat first my darling {1}!", Name, spouse.Name);
spoon.SetOwner(spouse);
continue;
}
// Spouse wasn't hungry, so finally eat
spoon.Use();
IsHungry = false;
Console.WriteLine("{0}: I am stuffed, my darling {1}!", Name, spouse.Name);
spoon.SetOwner(spouse);
}
}
}
}
}
Consider a UNIX system having 50 process slots.
Ten programs are running, each of which having to create 6 (sub)processes.
After each process has created 4 processes, the 10 original processes and the 40 new processes have exhausted the table. Each of the 10 original processes now sits in an endless loop forking and failing – which is aptly the situation of a livelock. The probability of this happening is very little but it could happen.
One example here might be using a timed tryLock to obtain more than one lock and if you can't obtain them all, back off and try again.
boolean tryLockAll(Collection<Lock> locks) {
boolean grabbedAllLocks = false;
for(int i=0; i<locks.size(); i++) {
Lock lock = locks.get(i);
if(!lock.tryLock(5, TimeUnit.SECONDS)) {
grabbedAllLocks = false;
// undo the locks I already took in reverse order
for(int j=i-1; j >= 0; j--) {
lock.unlock();
}
}
}
}
I could imagine such code would be problematic as you have lots of threads colliding and waiting to obtain a set of locks. But I'm not sure this is very compelling to me as a simple example.
Python version of jelbourn's code:
import threading
import time
lock = threading.Lock()
class Spoon:
def __init__(self, diner):
self.owner = diner
def setOwner(self, diner):
with lock:
self.owner = diner
def use(self):
with lock:
"{0} has eaten".format(self.owner)
class Diner:
def __init__(self, name):
self.name = name
self.hungry = True
def eatsWith(self, spoon, spouse):
while(self.hungry):
if self != spoon.owner:
time.sleep(1) # blocks thread, not process
continue
if spouse.hungry:
print "{0}: you eat first, {1}".format(self.name, spouse.name)
spoon.setOwner(spouse)
continue
# Spouse was not hungry, eat
spoon.use()
print "{0}: I'm stuffed, {1}".format(self.name, spouse.name)
spoon.setOwner(spouse)
def main():
husband = Diner("Bob")
wife = Diner("Alice")
spoon = Spoon(husband)
t0 = threading.Thread(target=husband.eatsWith, args=(spoon, wife))
t1 = threading.Thread(target=wife.eatsWith, args=(spoon, husband))
t0.start()
t1.start()
t0.join()
t1.join()
if __name__ == "__main__":
main()
I modify the answer of #jelbourn.
When one of them notices that the other is hungry, he(her) should release the spoon and wait another notify, so a livelock happens.
public class LiveLock {
static class Spoon {
Diner owner;
public String getOwnerName() {
return owner.getName();
}
public void setOwner(Diner diner) {
this.owner = diner;
}
public Spoon(Diner diner) {
this.owner = diner;
}
public void use() {
System.out.println(owner.getName() + " use this spoon and finish eat.");
}
}
static class Diner {
public Diner(boolean isHungry, String name) {
this.isHungry = isHungry;
this.name = name;
}
private boolean isHungry;
private String name;
public String getName() {
return name;
}
public void eatWith(Diner spouse, Spoon sharedSpoon) {
try {
synchronized (sharedSpoon) {
while (isHungry) {
while (!sharedSpoon.getOwnerName().equals(name)) {
sharedSpoon.wait();
//System.out.println("sharedSpoon belongs to" + sharedSpoon.getOwnerName())
}
if (spouse.isHungry) {
System.out.println(spouse.getName() + "is hungry,I should give it to him(her).");
sharedSpoon.setOwner(spouse);
sharedSpoon.notifyAll();
} else {
sharedSpoon.use();
sharedSpoon.setOwner(spouse);
isHungry = false;
}
Thread.sleep(500);
}
}
} catch (InterruptedException e) {
System.out.println(name + " is interrupted.");
}
}
}
public static void main(String[] args) {
final Diner husband = new Diner(true, "husband");
final Diner wife = new Diner(true, "wife");
final Spoon sharedSpoon = new Spoon(wife);
Thread h = new Thread() {
#Override
public void run() {
husband.eatWith(wife, sharedSpoon);
}
};
h.start();
Thread w = new Thread() {
#Override
public void run() {
wife.eatWith(husband, sharedSpoon);
}
};
w.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
h.interrupt();
w.interrupt();
try {
h.join();
w.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package concurrently.deadlock;
import static java.lang.System.out;
/* This is an example of livelock */
public class Dinner {
public static void main(String[] args) {
Spoon spoon = new Spoon();
Dish dish = new Dish();
new Thread(new Husband(spoon, dish)).start();
new Thread(new Wife(spoon, dish)).start();
}
}
class Spoon {
boolean isLocked;
}
class Dish {
boolean isLocked;
}
class Husband implements Runnable {
Spoon spoon;
Dish dish;
Husband(Spoon spoon, Dish dish) {
this.spoon = spoon;
this.dish = dish;
}
#Override
public void run() {
while (true) {
synchronized (spoon) {
spoon.isLocked = true;
out.println("husband get spoon");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
if (dish.isLocked == true) {
spoon.isLocked = false; // give away spoon
out.println("husband pass away spoon");
continue;
}
synchronized (dish) {
dish.isLocked = true;
out.println("Husband is eating!");
}
dish.isLocked = false;
}
spoon.isLocked = false;
}
}
}
class Wife implements Runnable {
Spoon spoon;
Dish dish;
Wife(Spoon spoon, Dish dish) {
this.spoon = spoon;
this.dish = dish;
}
#Override
public void run() {
while (true) {
synchronized (dish) {
dish.isLocked = true;
out.println("wife get dish");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
if (spoon.isLocked == true) {
dish.isLocked = false; // give away dish
out.println("wife pass away dish");
continue;
}
synchronized (spoon) {
spoon.isLocked = true;
out.println("Wife is eating!");
}
spoon.isLocked = false;
}
dish.isLocked = false;
}
}
}
Example:
Thread 1
top:
lock(L1);
if (try_lock(L2) != 0) {
unlock(L1);
goto top;
Thread 2
top:
lock(L2);
if (try_lock(L1) != 0) {
unlock(L2);
goto top;
The only difference is Thread 1 and Thread 2 try to acquire the locks in a different order. Livelock could happen as follows:
Thread 1 runs acquires L1, then a context switch occurs. Thread 2 runs acquires L2, then another context switch occurs. Thread 1 runs and cannot acquire L2, but before releasing L1 a context switch occurs. Thread 2 runs and cannot acquire L1, releases L2, and a context switch occurs. Thread 1 releases L1, and now we are basically back to the starting state, and in theory these steps could keep repeating forever.