I am new to learn multi-thread programming. I am told that thread - unsafe problem is always caused by something shared across multi thread. That makes sense for me, however, that seems can not explain the issue in below code which appears nothing is shared across multi thread.
package test;
public class Outputer{
public void output(){
String name = "123456789";
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
package test;
public class TraditionalThreadSynchronized {
public static void main(String[] args) {
Outputer outputer = new Outputer();
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 50; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 50; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output();
}
}
}).start();
}
}
what I expected is that 123456789 should be seen intact. But sometimes, I can see the output in console as below.
... ...
123456789
123456789
123456789
123456789
123456789
123456789 // expected
112323456789 // unexpected
456789 // unexpetecd
123456789
123456789
123456789
123456789
123456789
... ...
I understand the root cause is that when one thread is executing code snippet below, its cpu time segment is over so thread is not able to finish execution. Another thread get cpu time segment then start to execute below code snippet but also possible to not finish the execution. then first thread again get cup time segment then continue to execute from where it was stopped.
In a word, I am aware that the root cause is below code snippet is not Atomic operation.
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
My fix is to surround with synchronized block as below. Now it reaches my expectation. Looks good.
synchronized(this) {
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
However, I still have some doubts which is currently haunted my mind. Somebody help !!!
Is the statement below true ? Always ?
the thread - unsafe problem is ALWAYS caused by something shared across my multi thread
I am asking because I don't see any data shared across threads in my example. The variable name is local variable, not a pass-in parameter or pass-out parameter (returned parameter). So name is thread safe.
If the statement is true, what is shared by threads ?
If the statement is false, any other situation can caused thread unsafe without sharing data across threads ?
Related
I'm new to RxJava. Currently, I'm trying out samples and converting existing codes to Rx.
I have an existing API, which takes a large list of objects,
since server takes time to process a large number of inputs and also due to timeout issues I'm sending inputs to the API in batch wise. if I have 300 objects, I will pass it as batches of 10 objects. As in, first I call the API with first 10 items, waiting for the response, once I received the response, I will take the next 10, till I reach 300 items. Righ now I am using so many nested callbacks and flags to keep track of items and results. I need to convert it to Rx Java.
I tried something with buffer operator and its working as expected. Just wanted to know is there any better solution or is this the exact way to do. My code is given below.
Observable.range(1, 300)
.buffer(10)
.flatMap((integers) -> mockServerResult(integers))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<String>() {
#Override
public void onNext(#NonNull String s) {
Log.d(TAG, "onNext: " + s);
}
#Override
public void onError(#NonNull Throwable e) {
}
#Override
public void onComplete() {
}
});
}
public Observable<String> mockServerResult(List<Integer> integers) {
StringBuilder stringBuilder = new StringBuilder("server Results for ");
for (Integer integer : integers) {
stringBuilder.append(integer.toString()).append(",");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Observable.just(stringBuilder.toString());
}
I'm learning RX and would like to use Console.ReadLine as a source for observable sequences.
I know that I can create "IEnumerable" using "yield return", but for my concrete use case I've decided to create a C# event, so that potentially many observers will be able to share the same keyboard input.
Here is my code:
class Program
{
private delegate void OnNewInputLineHandler(string line);
private static event OnNewInputLineHandler OnNewInputLineEvent = _ => {};
static void Main(string[] args)
{
Task.Run((Action) GetInput);
var input = ConsoleInput();
input.Subscribe(s=>Console.WriteLine("1: " + s));
Thread.Sleep(30000);
}
private static void GetInput()
{
while (true)
OnNewInputLineEvent(Console.ReadLine());
}
private static IObservable<string> ConsoleInput()
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
OnNewInputLineHandler h = observer.OnNext;
OnNewInputLineEvent += h;
return Disposable.Create(() => { OnNewInputLineEvent -= h; });
});
}
}
My problem - when I run the GetInput method as it is shown above, the very first input line is not sent to the sequence (but it is sent to the event handler).
However, if I replace it with the following version, everything works as expected:
private static void GetInput()
{
while (true)
{
var s = Console.ReadLine();
OnNewInputLineEvent(s);
}
}
Could someone shed some light on why this might happen?
You're trying to make life difficult for yourself. There is almost always a way to make things simple with Rx. It's just a matter of learning to think more functionally rather than procedurally.
This is all you need:
class Program
{
static void Main(string[] args)
{
var subscription = ConsoleInput().Subscribe(s => Console.WriteLine("1: " + s));
Thread.Sleep(30000);
subscription.Dispose();
}
private static IObservable<string> ConsoleInput()
{
return
Observable
.FromAsync(() => Console.In.ReadLineAsync())
.Repeat()
.Publish()
.RefCount()
.SubscribeOn(Scheduler.Default);
}
}
This lets multiple subscribers share the one input through the .Publish().RefCount(). And the .SubscribeOn(Scheduler.Default) pushes the subscription out to a new thread - without it you block on a subscription.
If you move Task.Run((Action) GetInput); to after the subscription your code will work as desired. This is because in your original version, the first call of OnNewInputEvent(Console.ReadLine()) is run before you've hooked OnNewInputLineEvent to the observer.OnNext.
How do I close a stage in JavaFX 2 after some specific external event has occurred? Suppose I have a stage with a simple progress bar that is filled up by a Task (borrowed from another answer):
Task<Void> task = new Task<Void>(){
#Override
public Void call(){
for (int i = 1; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
updateProgress(i, 10);
}
return null;
}
};
How do I close the window automatically (and open the next one) after the Task is done and the ProgressBar is filled to 100%?
Before return null; you can add
Platform.runLater(
new Runnable() {
public void run() {
stage.close();
}
}
);
or
progressBar.progressProperty().addListener(new ChangeListener<Number>(){
//add checking, that progress is >= 1.0 - epsilon
//and call stage.close();
})
The first is better. But note, that task is done on a separate thread. so you should put a request on stage.close() on JFX thread using special call.
Also, jewelsea provides links on stage closing questions in comment to the question.
We are using MdbgCore.dll to evaluate a property off a parameter on a thread callstack.
To do this, we are performing a func-eval.
Unfortunately, all our attempts to perform the func-eval are failing with CORDBG_E_ILLEGAL_IN_OPTIMIZED_CODE, which seems to be due to the thread being used for the func-eval not being in a GC-safe point.
This is documented here: http://blogs.msdn.com/b/jmstall/archive/2005/11/15/funceval-rules.aspx.
We tried scanning all threads in the process to find a thread that is in a GC-safe point, but they all appear to have UserState marked with USER_UNSAFE_POINT.
There is very scarce documentation on the subject, and we are pulling our hair out trying to figure out if there is a way to get a thread in a GC-safe point so we can do the func-eval. We would consider anything that allows us to deterministically break into the process with a thread to do the func-eval with.
Disclaimer: we are trying to evaluate a method on a class that resides in an optimized assembly, so not sure if this is maybe also causing an issue.
The sample code follows:
if (argument.TypeName.EndsWith(
"WorkerRequest", StringComparison.OrdinalIgnoreCase)
&& !argument.IsNull)
{
try
{
// Invoke the "GetUriPath()" function to obtain the URI
string functionName = "System.Web.HttpWorkerRequest.GetUriPath";
MDbgFunction func = debugger.Processes.Active.ResolveFunctionNameFromScope(
functionName,
thread.CorThread.AppDomain
);
if (null == func)
{
throw new InvalidOperationException(
String.Format("Could not resolve {0}", functionName));
}
// Setup the eval
CorEval eval = threadForFuncEvals.CorThread.CreateEval();
// Setup the function parameters
List<CorValue> values = new List<CorValue>();
// Add the worker request "this" pointer
values.Add(
argument.CorValue
);
// resume the thread being used to do the func-eval
threadForFuncEvals.CorThread.DebugState = CorDebugThreadState.THREAD_RUN;
// Queue the function for execution
// EXCEPTION THROWN BELOW
// EXCEPTION THROWN BELOW
// EXCEPTION THROWN BELOW
eval.CallFunction(func.CorFunction, values.ToArray());
// BUGBUG: Should we pause all other threads to prevent them from moving?
// Continue the process to execute the function
if (!proc.Go().WaitOne(settings.BreakTimeout))
{
throw new InvalidOperationException("Timeout while evaluating function");
}
// get the returned string
var result = eval.Result;
if (result != null)
{
MDbgValue mv = new MDbgValue(proc, result);
string returnedValue = mv.GetStringValue(false);
threadInfo.Url = returnedValue;
}
}
catch (Exception e)
{
// BUGBUG: Ignoring exception
}
finally
{
// suspend the thread again
if (threadForFuncEvals != null)
{
threadForFuncEvals.CorThread.DebugState =
CorDebugThreadState.THREAD_SUSPEND;
}
}
}
Microsoft / Mdbg team, can you help?
Best,
Mike
Is this something to do with JIT optimization?
In my program, I turn JIT optimization off (for technical reasons, I think you can only do this with CreateProcess() and not using Attach()).
proc = m_Debugger.CreateProcess(ProcessName, ProcessArgs, DebugModeFlag.Default, DebugEngineUtils.GetAssemblyRuntimeVersion(ProcessName,DefaultNetVersion));
if (proc!=null) proc.CorProcess.OnCreateProcess += new Microsoft.Samples.Debugging.CorDebug.CorProcessEventHandler(CorProcess_OnCreateProcess);
if (proc!=null) proc.CorProcess.OnModuleLoad += new Microsoft.Samples.Debugging.CorDebug.CorModuleEventHandler(CorProcess_OnModuleLoad);
void CorProcess_OnModuleLoad(object sender, Microsoft.Samples.Debugging.CorDebug.CorModuleEventArgs e)
{
e.Module.JITCompilerFlags = Microsoft.Samples.Debugging.CorDebug.CorDebugJITCompilerFlags.CORDEBUG_JIT_DISABLE_OPTIMIZATION;
}
void CorProcess_OnCreateProcess(object sender, Microsoft.Samples.Debugging.CorDebug.CorProcessEventArgs e)
{
//try to disable optimization
((Microsoft.Samples.Debugging.CorDebug.CorProcess)sender).DesiredNGENCompilerFlags = Microsoft.Samples.Debugging.CorDebug.CorDebugJITCompilerFlags.CORDEBUG_JIT_DISABLE_OPTIMIZATION;
}
The following code is adapted from an example in Real-Time Java Platform Programming by Peter C. Dibble:
import javax.realtime.*;
public class OSTimer {
static volatile boolean cont = true;
public static void main(String[] args) {
AsyncEventHandler handler = new AsyncEventHandler(){
public void handleAsyncEvent() {
System.out.println("Stopping...");
cont = false;
}
}
};
OneShotTimer timer = new OneShotTimer(new RelativeTime(3000, 0), handler);
timer.start();
while(cont){
System.out.println("Running");
if (timer.isRunning()) System.out.println("Timer is running");
try {
Thread.sleep(1000);
} catch(Exception e) { }
}
System.exit(0);
}
The the program is supposed to run for 3 seconds and then exit. However, the output shows that while the timer did indeed stop after 3 seconds, the program continues as usual, i.e. output is:
Running
Timer is running
Running
Timer is running
Running
Timer is running
Running
Running
Running......
Clearly the handler did not fire, and I've no idea why. Another example program involving a periodic timer triggering the handler does work as expected. The program structure is almost the same as the one here.
A few things to try:
Call fire() explicitly on the timer instance to see if you can force things
Try creating your handler by passing in the logic as a Runnable object to the handler. The API is a little unclear on this, but this is how I have specified handlers in the past.
Example:
AsyncEventHandler handler = new AsyncEventHandler(new Runnable() {
public void run() {
System.out.println("Stopping...");
cont = false;
}
});