[Mono-list] Thread.Sleep --- bug or feature ?

Adrien Dessemond adrien.dessemond at softhome.net
Mon Nov 19 07:18:57 EST 2007


Hi Yury,

I didn't thought about what the "huge" delay come from precisely, but you
must never rely on duration to "lock" piece of codes (you have no control
on when your process is awakened by the scheduler). The best for you would
be to use the lock keyword (use a dummy object for that).

Thread1:

lock(alockObject) {
Operations....

}

Thread2 :

lock(theSamelockObjectAsInThread1) {
Operations...
}

You can still use your actual structure or do the job in seperate 2
threads (don't forget to use Thread.Join() to wait for your spawned thread
to finish before ending your program). Of course the locked code must be
as short as possible.

I don't have the time to dig in the internals of BigInteger this morning
but chances are that you face to strange symptoms because of the lack of a
correct locking mechanism (aka race condition) in your code.

Let me know if you need a bit more help than a global idea of the track to
follow.
Regards,

Adrien


On Sat, November 17, 2007 8:30 am, Yury Serdyuk wrote:
> Hi !
> I have found strange behave of the "Sleep" constuct in (multi-threaded)
> programs, which use some libraries (dll's).
>
> Concretely, my program launches some thread, which  makes some
> computations  and  uses Mono.Math.BigInteger class.
> It write results to some array of integers.
> Simultaneously, main thread traverses this array and falls to sleep if
> the next value is "unready":
>
>> using System;
>> using Mono.Math;
>> using System.Threading;
>>
>>
>> public  class Mono_Sleep_Bug {
>>
>>  public static int M = 50;
>>  public static bool contin = true;
>>
>>  public static int[] results;
>>
>>  public static void Main (  String[] args )  {
>>
>>   int i ;
>>
>>   int N = 2;
>>   results = new int[M]  ;
>>
>>   for ( i=0;  i < M ; i++ )
>>    results[ i ]  = 0;
>>
>>   ThreadStart tstart = new ThreadStart ( Worker );
>>   ( new Thread ( tstart ) ).Start();
>>
>>   i = 0  ;
>>
>>   while ( i  < N  )
>>   {
>>    while ( results[i]  == 0   )
>>    {
>>     DateTime dt1 = DateTime.Now;
>>     Thread.Sleep( 10  );
>>     DateTime dt2 = DateTime.Now;
>>     Console.WriteLine ( "Sleep time = " + (dt2-dt1).TotalSeconds );
>>    }
>>
>>    i++  ;
>>    Console.WriteLine( "*********i=" + i + "****************"  )  ;
>>
>>   }
>>
>>   contin  = false  ;
>>  }
>>
>>   public static void Worker ()
>>   {
>>    BigInteger L;
>>
>>    BigInteger one = new BigInteger( (uint)1  )  ;
>>
>>    int q  = 0;
>>
>>    while ( q < M   )
>>    { Console.WriteLine ( "q=" + q );
>>      L  = one;
>>
>>      for ( int j  = 0; j  < 100000; j++   )
>>        L = BigInteger.Add ( L, one );
>>
>>      results[ q ]  = 1;
>>      q  = q + 1;
>>
>>    }
>>
>>   }
>>
>> }
>
> While I use
> Sleep ( 10 );
> the process is awaked after 15 secs. !!!
>
>> [serdyuk at skif ]$ mono Mono_Sleep_Bug.exe
>> q=0
>> Sleep time = 0.030861
>> q=1
>>             .   .   .
>> q=48
>> q=49
>> Sleep time = 15.033854
>> *********i=1****************
>> *********i=2****************
>
>  From the other side, it's all OK for the equivalent program with "long"
> integers in place of BigIntegers:
>
>> using System;
>> using Mono.Math;
>> using System.Threading;
>>
>>
>> public  class Mono_Sleep_Bug_long {
>>
>>  public static int M = 50;
>>  public static bool contin = true;
>>
>>  public static int[] results;
>>
>>  public static void Main (  String[] args )  {
>>
>>   int i ;
>>
>>   int N = 2;
>>   results = new int[M]  ;
>>
>>   for ( i=0;  i < M ; i++ )
>>    results[ i ]  = 0;
>>
>>   ThreadStart tstart = new ThreadStart ( Worker );
>>   ( new Thread ( tstart ) ).Start();
>>
>>   i = 0  ;
>>
>>   while ( i  < N  )
>>   {
>>    while ( results[i]  == 0   )
>>    {
>>     DateTime dt1 = DateTime.Now;
>>     Thread.Sleep( 10  );
>>     DateTime dt2 = DateTime.Now;
>>     Console.WriteLine ( "Sleep time = " + (dt2-dt1).TotalSeconds );
>>    }
>>
>>    i++  ;
>>    Console.WriteLine( "*********i=" + i + "****************"  )  ;
>>
>>   }
>>
>>   contin  = false  ;
>>  }
>>
>>   public static void Worker ()
>>   {
>>    long L;
>>
>>    long one = 1;
>>
>>    int q  = 0;
>>
>>    while ( q < M   )
>>    { Console.WriteLine ( "q=" + q );
>>      L  = one;
>>
>>      for ( int j  = 0; j  < 1000000; j++   )
>>        L = L + one;
>>
>>      results[ q ]  = 1;
>>      q  = q + 1;
>>
>>    }
>>
>>   }
>>
>> }
>
>> [serdyuk at skif ]$ mono Mono_Sleep_Bug_long.exe
>> q=0
>> q=1
>> Sleep time = 0.035377
>> *********i=1****************
>> q=2
>> q=3
>> Sleep time = 0.01327
>> *********i=2****************
>> q=4
>>                 . .  .
>>
>> q=47
>> q=48
>> q=49
>
> Some details about runs:
> 1) to compile Mono_Sleep_Bug
>  >mcs /r:Mono.Security Mono_Sleep_Bug42.cs
> 2)  $ uname -a
> Linux skif 2.4.27 #1 SMP Thu Apr 14 15:25:11 MSD 2005 i686 athlon i386
> GNU/Linux
> 3) $ mono -V
> Mono JIT compiler version 1.2.5.2 (tarball)
> Copyright (C) 2002-2007 Novell, Inc and Contributors. www.mono-project.com
>         TLS:           __thread
>         GC:            Included Boehm (with typed GC)
>         SIGSEGV:       normal
>         Architecture:  x86
>         Disabled:      none
>
> Moreover, this effect is occured using arbitrary library ( for big
> numbers).
> In particularly, at first I have faced with this problem trying to use
> Oyster.IntX.dll
> (http://contest2005.gotdotnet.ru/Request/Tools/UtilitiesLib/Downloads_GetFile.aspx?id=169728).
>
> But under Windows it's OK (in particularly, with Oyster.IntX.dll).
>
> Please, help.
>
> Best wishes,
>                      Yury Serdyuk.
>
> _______________________________________________
> Mono-list maillist  -  Mono-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
>




More information about the Mono-list mailing list