尝试从锁定部分调用Console.WriteLine,但似乎它无法正常工作 - 控制台未锁定。下面是简单应用程序的代码 - 两个线程并行填充列表,出于调试目的,我打印有关线程工作和新添加元素的信息。
using System;
using System.Threading;
using System.Collections.Generic;
class ThreadSafe
{
static object SyncRoot = new object();
static int threadsCount = 0;
static List<string> list = new List<string>();
static void Main()
{
Thread t1 = new Thread(AddItems);
Thread t2 = new Thread(AddItems);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
PrintItems();
Console.ReadLine();
}
static void PrintItems()
{
string[] items;
Console.WriteLine("Converting list to array...");
items = list.ToArray();
Console.WriteLine("Printing array...");
foreach (string s in items)
Console.WriteLine(s);
}
static void AddItems()
{
int threadNo = threadsCount;
threadsCount++;
{
Console.WriteLine("Populating list from {0} item in thread N {1}...", list.Count, threadNo);
for (int i = 0; i < 50; i++)
{
lock (SyncRoot)
{
Console.Write("Population. Thread N {0} is running. ", threadNo);
Console.WriteLine("Element N {0} has been added successfully.", list.Count);
list.Add("Item " + list.Count);
}
}
}
}
}
结果:
Populating list from 0 item in thread N 1...
Population. Thread N 1 is running. Element N 0 has been added successfully.
Population. Thread N 1 is running. Element N 1 has been added successfully.
Population. Thread N 1 is running. Element N 2 has been added successfully.
Population. Thread N 1 is running. Element N 3 has been added successfully.
Population. Thread N 1 is running. Element N 4 has been added successfully.
Population. Thread N 1 is running. Element N 5 has been added successfully.
Population. Thread N 1 is running. Element N 6 has been added successfully.
Population. Thread N 1 is running. Element N 7 has been added successfully.
Population. Thread N 1 is running. Element N 8 has been added successfully.
Population. Thread N 1 is running. Element N 9 has been added successfully.
Population. Thread N 1 is running. Element N 10 has been added successfully.
Population. Thread N 1 is running. Element N 11 has been added successfully.
Population. Thread N 1 is running. Element N 12 has been added successfully.
Population. Thread N 1 is running. Element N 13 has been added successfully.
Population. Thread N 1 is running. Element N 14 has been added successfully.
Population. Thread N 1 is running. Element N 15 has been added successfully.
Population. Thread N 1 is running. Populating list from 0 item in thread N 0...
Element N 16 has been added successfully.
Population. Thread N 0 is running. Element N 17 has been added successfully.
Population. Thread N 0 is running. Element N 18 has been added successfully.
Population. Thread N 0 is running. Element N 19 has been added successfully.
在第15步和第16步之间以某种方式新的第一个开始运行并在锁定部分中的Console.Write和Console.WriteLine调用之间输出它的东西...... Console.WriteLine确实是非线程安全的吗?或者我做错了什么?
谢谢!
答案 0 :(得分:4)
你有两个AddItems
个线程,每个线程都有一个解锁输出(函数中的第一个)。这种交错是预期的行为。你需要:
lock (SyncRoot)
{
Console.WriteLine("Populating list from {0} item in thread N {1}...", list.Count, threadNo);
}
答案 1 :(得分:2)
该行:
Console.WriteLine("Populating list from {0} item in thread N {1}...", list.Count, threadNo);
出现在synchronized块之外。
答案 2 :(得分:1)
您的部分代码位于锁定部分之外。第一件事:
int threadNo = threadsCount;
threadsCount++;
不是线程安全的。想象一下,线程启动并被第二个线程中断,然后才能增加线程数。然后两个线程都有threadNo = 0
但这似乎不是一个问题,虽然如果你使用它会导致问题做一些计算。
正如其他人所指出的那样:你还需要锁定Console.WriteLine("Populating list from {0} item in thread N {1}...", list.Count, threadNo);
,所以当下一个线程启动时,它会等待在控制台上写入而另一个线程也在写入。
答案 3 :(得分:0)
Console.WriteLine(“从线程N {1}中的{0}项填充列表...”,list.Count,threadNo);不在锁定区域内,因此可以随时打印。