List 集合线程安全测试

最近在做一些代码整理工作,涉及到List 线程安全问题,查了一些资料。网上有些资料说List 增减成员(Add , Remove) 是安全的,但不保证成员属性值访问安全性,及禁止对 List 跨线程遍历访问, 如 foreach 遍历。
可以想象,有些跨线程操作(Add , Remove)List 集合时, 恰好 另一个线程正在通过 foreach遍历, 这时会抛出异常) 。 有改进方案用 for 替代 foreach ,这样仍会报下标越界错误。
因此 , 跨线程遍历list 不安全毋庸置疑。 对List 增减成员是否安全,需要验证才知道。

如下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace testQueue
{
    class Program
    {
        static List<int> list = new List<int>();
        static ManualResetEvent[] manu;
        static object LockList = new object();

        static void Main(string[] args)
        {
            manu = new ManualResetEvent[2];
            manu[0] = new ManualResetEvent(false);
            manu[1] = new ManualResetEvent(false);

            ThreadPool.QueueUserWorkItem(new WaitCallback(Task1));
            ThreadPool.QueueUserWorkItem(new WaitCallback(Task2));

            //等待完成
            ManualResetEvent.WaitAll(manu);

            //统计结果:
            Console.WriteLine("count:{0}", list.Count);

            Console.ReadKey();
        }

        public static void Task1(object obj)
        {
            // lock (LockList)
            //  {
            for (int i = 0; i < 5000000; i++)
            {
                list.Add(i);
            }
            //  }

            Console.WriteLine("Task1 complete!");
            manu[0].Set();
        }

        public static void Task2(object obj)
        {
            //  lock (LockList)
            // {
            for (int i = 0; i < 5000000; i++)
            {
                list.Add(i);
            }
            // }
            Console.WriteLine("Task2 complete!");
            manu[1].Set();
        }
    }
}

结果:

我们知道, List 集合大小是动态分配的,此处表明,分配List 大小,与对 List 操作 , 应保证在同一线程。  为了避免List 运行中分配大小,在初使化时,设置了List 大小:

static List<int> list = new List<int>(10000000);

再看看结果:

增加线程锁结果:

结论:

此处表明,使用 List 跨线程操作,增减成员也需加锁。否则会有各种问题。
有关线程集合安全访问, 微软在 .Net Framework 4 时,提供了线程安全集合命名空间:

System.Collections.Concurrent

时间: 2024-10-29 11:24:35

List 集合线程安全测试的相关文章

集合线程安全

除了System.Collections.Concurrent目录下集合外,非泛型集合使用lock(非泛型集合对象.SyncRoot)进行锁定达到集合线程安全目的 泛型集合使用static object sycObj = new object(); //是否static看具体应用 lock (sycObj){//操作集合.}

Python_线程、线程效率测试、数据隔离测试、主线程和子线程

0.进程中的概念 三状态:就绪.运行.阻塞 就绪(Ready):当进程已分配到除CPU以外的所有必要资源,只要获得处理机便可立即执行,这时的进程状态成为就绪状态. 执行/运行(Running)状态:当进程已获得处理机,其程序正在处理机上执行,此时的进程状态成为执行状态. 阻塞(Blocked)状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态.引起进程阻塞的事件可有多种,例如,等待I/O完成.申请缓冲区不能满足.等待信件(信号)等. 同步:一个任务的完成需要依赖另外

ArrayList的线程安全测试

public class TestThread implements Runnable{ private List list; CountDownLatch cdl; public TestThread(List list,CountDownLatch cdl){ this.list=list; this.cdl=cdl; } /** * @see java.lang.Runnable#run() */ @Override public void run() { for(int i=0;i<50

ArrayList,Vector线程安全性测试

结论:如果集合不是线程安全的话,在多线程情况下插入数据会出现数据丢失的问题. Java代码   import java.util.ArrayList; import java.util.List; //实现Runnable接口的线程 public class HelloThread implements Runnable { String name; List<String> v; HelloThread(String name, List<String> v) { this.na

简单的线程Runnable实现线程的测试

/*  需求:  写一个简单的线程测试,采用实现的Runnable的run()  打印一句句简单自定义线程名字的语句Thread World Wecome You!!  和默认的线程名字的语句:This is defalut ThreadName:默认的线程名字*/    class TEST_Thread implements Runnable{       private String name;        public void getName(String name){       

线程中测试getName方法和getId方法

测试Thread类的getName方法和getI的方法,1.创建两个线程,输出默认的线程名字和默认的ID.2.创建一个线程,设置线程的名字并输出线程名字和默认ID. 一.获取默认的线程名字和ID,首先,新建类TestThreadNameAndId,在该类的main方法中,创建两个线程t0.t1:接着分别使用Thread类的getName方法和getId方法获取线程的名字和ID. //获取线程名字及IDpublic class TestThreadNameAndId {    //测试线程的get

39、集合线程安全问题

由于Set.List和Map都是线程不安全的,为了同步控制,Collections类提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题,例如: 1 public class Test { 2 3 public static void main(String[] args) { 4 5 Collection c=Collections.synchronizedCollection(new ArrayList()

1024个读出线程的测试结果

1024个读出线程,发送端不控制速度.测试包长2KB, 测试时间983秒时, 单个线程的带宽为0.0068Gb/s, 此时的拥塞窗口为17,rtt为45000. 发送端的cpu占用率为18%, 接收端的CPU占用率为34%.接收端的Recv-Q为0,发送端的Send-Q为几百KB. 发送端和接收端先建立1024个连接,然后再用pthread_create创建1024个线程,发送端每个线程调用send()函数发送数据,接收端每个线程调用recv()函数接收数据. 在发送数据的初期,单线程的带宽达到

Ultimate thread group线程组和Stepping thread group线程组测试场景

Ultimate thread group线程组 当测试需求是要求进行波浪型的压力测试场景时,使用该线程组,例如:测试场景总共有10个线程,然后分为三个波段进行测试,每个波段负载策略设置为一样,如图: 注意,这里是设置了三个线程计划,每个线程计划并发10个,是在时间轴上按顺序执行的,因此场景最高并发用户是10个,而非30个并发用户. 2.当测试需求是要求进行阶梯型的压力测试场景时,使用该线程组.例如:测试场景总共有30个线程,然后分为三次逐渐增加负载,每次增加负载10个线程,如图: 注意,这里是