0
using System;
using System.Threading;
using System.Text;

class ThreadTest
{
    static StringBuilder sb = new StringBuilder();
    static void Main()
    {


        Thread t = new Thread(WriteY);
        t.Start();

        for(int i = 0; i < 1000; i++)
        {
            sb.Append("x");

        }
        Console.WriteLine(sb.ToString());
    }

    private static void WriteY()
    {
        for (int i = 0; i < 1000; i++)
        {
            sb.Append("y");
        }
    }
}

output: {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy}

Question:

  1. Why does 'x' appear before 'y'?
  2. StringBuilder is Accept only one Thread?
  3. Why does not appear like this "xyxyxyxyx xyxyxyxy"?
FaizanHussainRabbani
  • 3,256
  • 3
  • 26
  • 46
Mr.feel
  • 315
  • 1
  • 3
  • 12
  • 3
    It's not guaranteed that x will appear before y (it's not even guaranteed that y will appear at all), but, generally speaking, it takes time for a new thread to start, so by the time it does, your `sb.Append("x")` has already executed. `t.Start()` is a non-blocking call. – Simon MᶜKenzie Feb 21 '18 at 04:52
  • Note also that if you increase your loop length to something large (I used 10,000), you _will_ see interleaving of x and y (at least I do on my machine). 1,000 cycles just don't take long enough for this sort of test! You will probably also receive an exception when you call `ToString()`, as `StringBuilder` is not thread safe, and can become corrupted when multiple threads try to write to it. To make this sort of thing reliable, you will need some sort of mutual exclusion - a very simple solution in your case would be `lock(sb)` on any call which interacts with the `StringBuilder`. – Simon MᶜKenzie Feb 21 '18 at 05:08
  • Did you need to paste 1000 chars each? – Furkan Kambay Feb 21 '18 at 05:16

2 Answers2

0

Is this what you are looking for?

class Program
{
    static StringBuilder sb = new StringBuilder();
    static void Main()
    {


        Thread t = new Thread(WriteY);
        t.Start();

        for (int i = 0; i < 1000; i++)
        {
            //Console.Write("x");
            sb.Append("x");
            Thread.Sleep(10);
        }

        //t.Join();
        Console.WriteLine(sb.ToString());
    }

    private static void WriteY()
    {
        for (int i = 0; i < 1000; i++)
        {
            //Console.Write("y");
            sb.Append("y");
            Thread.Sleep(10);
        }
    }
}

Why does 'x' appear before 'y'?

Because the main thread is not blocked at any point and continuing its execution before the resources are granted to other thread that is printing y

StringBuilder is Accept only one Thread?

No that is not the case. Run example below.

Why does not appear like this "xyxyxyxyx xyxyxyxy"?

there is not much work so, to get that random result you need to increase the duration which is demonstrated by using sleep.

Update: in your above example you can see the randomness if you increase your loop to 100000 or greater. and you also need to add t.Join() otherwise you thread may not yield the work.

Mujahid Daud Khan
  • 1,983
  • 1
  • 14
  • 23
0

Questions 1 and 3 are both related to the time slicing of the Windows scheduler. According to the Windows 2000 Performance Guide, a time slice on x86 processors is about 30 ms. That may have changed since Windows 2000, but should still be in this order of magnitude. Hence, t.Start() only adds the new thread to the scheduler but does not immediately trigger a context switch to it. The main thread has still the remaining part of its time slice, which obviously is enough time to print the 'x' 1,000 times.

Furthermore, when the new thread is actually scheduled, it has a whole time slice to print out 'y'. As this is plenty of time, you don't get the pattern "xyxyxy", but rather 'x's until the time slice of the main thread runs out and then 'y's until the end of the time slice of the new thread and then 'x's again. (At least if there are enough 'x's and 'y's to be printed, which, according to Simon's comment is the case with 10,000 'x's and 'y's.)

Question 2 is answered by the MSDN page on the StringBuilder. Under the topic "Thread Safety" it is written that "Any public static ( Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe." As the Append method is an instance method, you cannot call this reliably from different threads in parallel without further synchronization.

Kristof U.
  • 1,263
  • 10
  • 17