Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a program which uses two client threads and a server. There is a point in my program where I want a value in one thread to influence the path of another thread.

More specifically, I have this code in the server:

class Handler 
{
    public void clientInteraction(Socket connection, bool isFirstThread, Barrier barrier)

    {
        string pAnswer = string.Empty;
        string endGameTrigger = string.Empty;
        //setup streamReaders and streamWriters

        while(true) //infinite game loop
        {
            //read in a question and send to both threads.
            pAnswer = sr.ReadLine();
            Console.WriteLine(pAnswer);

            awardPoints(); 

            writeToConsole("Press ENTER to ask another question or enter 0 to end the game", isFirstThread);
            if(isFirstThread == true)
            {
                endGameTrigger = Console.ReadLine(); //this is only assigning to one thread...
            }

            barrier.SignalAndWait();

            if(endGameTrigger == "0")//...meaning this is never satisfied in one thread
            {
                endGame();
            }           

        }
    }
}   

The boolean value isFirstThread is a value set up in the constructor of the thread to which I can detect which thread was connected first.

Is there some way, or perhaps a threading method, that will allow the second connected thread to detect that the endGameTrigger in the first thread has been set and therefore both threads execute the endGame() method properly.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
123 views
Welcome To Ask or Share your Answers For Others

1 Answer

It's best to be concerned with multithreading

  • If it's absolutely necessary to start a separate thread for performance/UI reasons
  • If your code may be running in a multithreaded environment (like a web site) and you need to know that it won't break when multiple threads operate on the same class or same values.

But exercise extreme caution. Incorrect use/handling of multiple threads can cause your code to behave unpredictably and inconsistently. Something will work most of the time and then not work for no apparent reason. Bugs will be difficult to reproduce and identify.

That being said, one of the essential concepts of handling multithreading is to ensure that two threads don't try to update the same value at the same time. They can corrupt or partially modify values in ways that would be impossible for a single thread.

One way to accomplish this is with locking.

private object _lockObject = new Object();
private string _myString;

void SetStringValue(string newValue)
{
    lock(_lockObject)
    {
        _myString = newValue;
    }
}

You generally have an object that exists only to serve as a lock. When one thread enters that lock block it acquires a lock on the object. If another thread already has a lock on that object then the next thread just waits for the previous thread to release the lock. That ensures that two threads can't update the value at the same time.

You want to keep the amount of code inside the lock as small as possible so that the lock is released as soon as possible. And be aware that if it gets complicated with multiple locks then two threads can permanently block each other.

For incrementing and updating numbers there are also interlocked operations that handle the locking for you, ensuring that those operations are executed by one thread at a time.

Just for fun I wrote this console app. It takes a sentence, breaks it into words, and then adds each word back onto a new string using multiple threads and outputs the string.

using System;
using System.Threading.Tasks;

namespace FunWithThreading
{
    class Program
    {
        static void Main(string[] args)
        {
            var sentence =
                "I am going to add each of these words to a string "
                + "using multiple threads just to see what happens.";
            var words = sentence.Split(' ');
            var output = "";
            Parallel.ForEach(words, word => output = output + " " + word);
            Console.WriteLine(output);
            Console.ReadLine();
        }
    }
}

The first two times I ran it, the output string was exactly what I started with. Great, it works perfectly! Then I got this:

I am going to add of these words to a string using multiple threads just to see what happens. each

Then I ran it 20 more times and couldn't repeat the error. Just imagine the frustration if this was a real application and something unpredictable like this happened even though I tested over and over and over, and then I couldn't get it to happen again.

So the point isn't that multithreading is evil, but just to understand the risks, only introduce it if you need to, and then carefully consider how to prevent threads from interfering with each other.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...