精华内容
下载资源
问答
  • 每个线程都有它自己独立的线程上下文,例如:栈、程序计数器、线程ID、条件码等,每个线程和其它的线程一起共享除此之外的进程上下文的剩余部分,包括整个用户的虚拟地址空间,当然也共享同样的打开的文件的集合。...
    一组并发线程运行在一个进程的上下文中,每个线程都有它自己独立的线程上下文,例如:栈、程序计数器、线程ID、条件码等,每个线程和其它的线程一起共享除此之外的进程上下文的剩余部分,包括整个用户的虚拟地址空间,当然也共享同样的打开的文件的集合。,这里有一点要特别注意,就是寄存器是从不共享的,而虚拟存储器总是共享的。
    
    有了共享就要防止在对共享变量进行操作的过程中得到一个不可知的值,在Linux内核中有个原子类型与原子操作这么个概念,因为用户态下没有这么一个原子操作存在,那么在我们用户态下就需要要对操作这个共享变量的线程进行同步。为什么要进行同步呢?
    因为假设我们在一个程序中有一个全局变量cnt,初始值为0,接下去我们创建了两个线程,完成的功能都是在一个循环中对这个变量进行+1操作,想象一下在这两个线程操作完成后会出现什么状况。
    1. void *thread(void* value)
    2. {
    3.      int max = *((int*)value)
    4.  
    5.      for(int i=0;i<max;i++)
    6.      {
    7.            cnt++; 
    8.      }
    9.      return NULL;
    10. }
    11. 假设我们这里的max为10000,那么我们想要得到的结果的结果当然是20000,可是在执行之后结果并不是我们所期望的20000,而是一个小于20000的值。为什么会出现这个现象呢?
      这里就是我们为什么需要对线程进行同步了。
      因为在C语言的层面来说,cnt++就是一条语句,实际上我们在心里默认把它当作了一个原子操作,事实上,就这么一条操作语句,在汇编代码中是分三步执行的:
      1)、将这个值从内存中取出来,放入一个寄存器中;
      2)、将寄存器中的值进行+1操作;
      3)、将寄存器中的值放入内存中去。
    12. 因为对与多线程来说我们不知道何时会执行哪个线程,所以执行的顺序是不可知的。我们所想的是先让一边执行完,然后再开始执行另外一边。
      现在我们不妨将这个问题极端化,也就是两线程交叉执行,假设左边的执行线程为A,右边为B,假设A先执行,A从内存中取出cnt的值,那么现在在R1里的值为0,接下去,A线程被B线程打断,A停止执行,B开始执行,B又从内存中取出cnt的值,现在在R2中的值也为0。然后又轮到A执行,进行加1操作,则R1为1,接下去轮到B执行,进行加1操作,则R2为1。然后A将值写回到内存中,B也将值写回到内存中。这次我们知道内存中的值为1而并非我们所期望的2。
      那么怎么能让它进行正确的执行顺序呢?同步,可以用加锁来完成同步操作。
      1. for(int i=0;i<max;i++)
      2. {
      3.     //加锁;
      4.     cnt++;
      5.     //减锁;
      6. }
      在对cnt加1的操作时,对这个操作加锁,这就意味着当下只有这一个线程执行这个操作,其它的线程都得等在外面,等这个线程解锁出来,其他的线程才可以有机会进去。
      加锁之后我们再来看看上面的那张图的执行过程,也假设是在一个极端的情况:
      A先加锁,然后完成那三个步骤(因为此时只有它一个线程有操作的权限),解锁;现在内存中的值为1,A加锁,然后一样完成三个步骤,解锁;现在内存中的值为2。与所期望的相同。当然了,对于加锁的问题还要防止出现死锁现象,这里就不讨论了。


    展开全文
  • C# 多线程中集合数据同步

    千次阅读 2007-12-09 19:32:00
    本文主要介绍C# 多线程中集合数据同步的实现方法。集合类通常不是线程安全的,多个阅读器可以安全的读取集合。但是对集合的任何修改都将为访问集合的所有线程生成不明确的结果,使用以下任何方法都可以令集合类是...
    本文主要介绍C# 多线程中集合数据同步的实现方法。集合类通常不是线程安全的,多个阅读器可以安全的读取集合。但是对集合的任何修改都将为访问集合的所有线程生成不明确的结果,使用以下任何方法都可以令集合类是线程安全的。
    

      (1) 使用Synchronized 方法,则从该类派生包装,并通过该包装以独占方式访问集合

      (2) 如果该类没有Synchronized 方法,则从该类派生并使用SyncRoot属性实现Synchronized 方法.

      (3) 在访问该集合时对SyncRoot属性使用锁定机制

      这一段时间在公司做多线程的东西比较多,所以把一些心得写了下来,对关注这一块的朋友有个提示作用.

      大家可以看看以下代码:

    以下是引用片段:
    class Program
      {
      static void Main(string[] args)
      {
      Program pg = new Program();
      //写线程
      Thread t1 = new System.Threading.Thread(new ThreadStart(pg.t1fun));
      // 读线程
      Thread t2 = new System.Threading.Thread(new ThreadStart(pg.t2fun));
      //删线程
      Thread t3 = new System.Threading.Thread(new ThreadStart(pg.t3fun));
      t1.Start();
      t2.Start();
      t3.Start();
      }
      ArrayList arraylist = new ArrayList();
      public void t1fun()
      {
      while (true)
      {
      arraylist.Add("t1--写入");
      System.Console.Out.WriteLine("写入");
      System.Threading.Thread.Sleep(1000);
      }
      }
      public void t2fun()
      {
      while (true)
      {
      for (int i = arraylist.Count - 1; i >= 0; i--)
      {
      System.Console.Out.WriteLine("t2读取:"+(string)arraylist[i]);
      }
      System.Threading.Thread.Sleep(1000);
      }
      }
      public void t3fun()
      {
      while (true)
      {
      for (int i = arraylist.Count - 1; i >= 0; i--)
      {
      arraylist.RemoveAt(i);
      System.Console.Out.WriteLine("t3删除:t1"+i.ToString());
      }
      System.Threading.Thread.Sleep(1000);
      }
      }
      }

      这个测试程序得简单,大家一看就明白了你可以运行一下看看,程序一会就挂了,揭示异常。

      未处理的异常:System.ArgumentOutOfRangeException: 索引超出范围。必须为非负值并小于集合大小。

      这就是因为多线程中对共享的集合资源同步引起的

      下面是改后的代码:

    以下是引用片段:
    class Program
      {
      static void Main(string[] args)
      {
      Program pg = new Program();
      //写线程
      Thread t1 = new System.Threading.Thread(new ThreadStart(pg.t1fun));
      // 读线程
      Thread t2 = new System.Threading.Thread(new ThreadStart(pg.t2fun));
      //删线程
      Thread t3 = new System.Threading.Thread(new ThreadStart(pg.t3fun));
      t1.Start();
      t2.Start();
      t3.Start();
      }
      ArrayList arraylist = new ArrayList();
      public void t1fun()
      {
      while (true)
      {
      lock (arraylist.SyncRoot)
      {
      arraylist.Add("t1--写入");
      }
      System.Console.Out.WriteLine("写入");
      System.Threading.Thread.Sleep(1000);
      }
      }
      public void t2fun()
      {
      while (true)
      {
      lock (arraylist.SyncRoot)
      {
      for (int i = arraylist.Count - 1; i >= 0; i--)
      {
      System.Console.Out.WriteLine("t2读取:" + (string)arraylist[i]);
      }
      }
      System.Threading.Thread.Sleep(1000);
      }
      }
      public void t3fun()
      {
      while (true)
      {
      lock (arraylist.SyncRoot)
      {
      for (int i = arraylist.Count - 1; i >= 0; i--)
      {
      arraylist.RemoveAt(i);
      System.Console.Out.WriteLine("t3删除:t1" + i.ToString());
      }
      }
      System.Threading.Thread.Sleep(1000);
      }
      }
      }
     
    展开全文
  • 线程访问共享对象和数据的方式 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象有那个共享数据,例如,买票系统就可以这么做。 2.如果每个线程执行的代码不同,这时候需要用...

     多个线程访问共享对象和数据的方式

           1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做。

           2.如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享:
                将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。
                将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。
                上面两种方式的组合:将共享数据封装在另外一个对象中,每个线程对共享数据的操作方法也分配到那个对象身上去完成,对象作为这个外部类中的成员变量或方法中的局部变量,每个线程的Runnable对象作为外部类中的成员内部类或局部内部类。

                总之,要同步互斥的几段代码最好是分别放在几个独立的方法中,这些方法再放在同一个类中,这样比较容易实现它们之间的同步互斥和通信。


         3.极端且简单的方式,即在任意一个类中定义一个static的变量,这将被所有线程共享(慎用)。


    package cn.itcast.lishehe;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    /** 李社河-2015年6月12日
     * 题目要求:构造两线程,要求: 
     *    (1)两线程并发操作  (这就要求不能使用syschronized关键字) 
     *    (2)要求两线程分别访问各自的数据data,互不干扰(可以使用Map集合,以Thread.currentThread()作为key,以data作为value) 
     *    (3)线程内有A、B两个模块,模块之间共享数据data  
     **/
    public class Thread2ThreadDataIndependent {  
         static Map<Thread,Integer> threadMap = new HashMap<Thread, Integer>();  
        public static void main(String[] args) {  
            for (int i = 0; i < 2; i++) {  
                new Thread(new Runnable() {  
                      
                    @Override  
                    public void run() {  
                        int data = new Random().nextInt(); //这里的data必须定义为局部变量,否则线程间不能实现数据独立  
                        System.out.println(Thread.currentThread().getName()+" has put data: "+data);  
                        threadMap.put(Thread.currentThread(), data);  
                        new A().get();  
                        new B().get();  
                    }  
                }).start();  
            }  
        }  
          
        static class A{  
            public void get(){  
                int data = threadMap.get(Thread.currentThread());  
                System.out.println("A from "+Thread.currentThread().getName()+" get data :"+data);  
            }  
        }  
        static class B{  
            public void get(){  
                int data = threadMap.get(Thread.currentThread());  
                System.out.println("B from "+Thread.currentThread().getName()+" get data :"+data);  
            }  
        }  
    }  

    运行结果


    展开全文
  • .Net Framework下的多线程安全集合

    千次阅读 2012-03-03 15:37:26
    .net framework 4.0增加了一个新的System.Collections.Concurrent命名空间,使得多线程开发不同线程间共享数据的问题解决起来更加轻松。特别是当你打算实现一个 producer/consumer 模式时,新提供的相关集合将会...

     每个正式发布的.net framework版本在增加特性时,都会着眼于那些对于当今程序员有挑战的问题上。.net framework 4.0增加了一个新的System.Collections.Concurrent命名空间,使得多线程开发中不同线程间共享数据的问题解决起来更加轻松。特别是当你打算实现一个 producer/consumer 模式时,新提供的相关集合将会帮助你完成不少工作。.net 4.0之前人们也会开发多线程程序,但是4.0中推出的这些新的集合后,意味着现在开发一个多线程序,你可以只做很少的事情framework将承担更多的工作。在微软程序员Alexandra Rusina的并行开发系列文章中,其中有一篇博文正是介绍这些集合类的。本文将深入这些集合类的设计,讨论它们解决了哪些问题,以及如何更好的在你的程序中使用它们;还会指出我所看到的由开发者对于这些集合类型能做什么不能做什么的误解引发的常见问题。

    ps:本文相关源代码已经提供在线下载

    使用新集合类型开发并行程序

    .net4.0之前开发并行程序,如果多个线程需要访问一个共享集合只能自己动手来实现同步。每次编辑集合元素时,需要手工锁定集合;可能还需要在每次集合访问(或是枚举成员)时也进行集合的锁定。以上就是一个最简单的多线程场景。有些应用程序会创建一个背景线程用来随时传递数据到线程共享集合。其它线程会读取和处理这些数据。要满足该场景,需要实现线程间自己的消息传递计划,当有可用新数据或是有数据消毁时通知其它线程。System.Collections.Concurrent 命名空间下包含了相关类和接口来提供以上所需功能及其它多线程开发中常见问题,包括跨线程的数据共享。

    System.Collections.Concurrent namespace命名空间中包含了五个不同的集合类型:BlockingCollection<T>, ConcurrentBag<T>, ConcurrentDictionary<TKey, TValue>, ConcurrentQueue<T> and ConcurrentStack<T>.此处我打算论述一下这五个类型的共性和设计目标,而不是逐个详细介绍以及论述它们的差异。这几个集合类中的部分实现了接口:IProducerConsumer<T> ,该接口抽象了实现Producer / Consumer 模式需要的相关功能。在你的应用开发中选用哪种集合类,和我们在选择泛型集合类时相同,也就是考虑他们在不同搜索及索引行为下表现的不同执行特征。

    本文使用的例子是我用WPF写的一个生成 曼德勃罗集 的应用。每个producer 线程负责生成整图中一块64X64 大小的像素值集合。Consumer线程在一个WritableBitmap上绘制用于显示的点。你可以单击图像中的任意位置来放大局部,也可以变换图中分布的颜色从而产生一些有趣的视觉效果。以上工作都可以通过System.Collections.Concurrent命名空间中的BlockingCollection<T>来轻松实现。

    运行该例子时,起初你将看到 从左上角的点(-2,-1) 开始的曼德勃罗集。黑色区域为集合内,其它彩色样点在集合外。

    本例提供了两个简单功能来帮助你探秘 曼德勃罗集 的效果。首先,点击图中任意位置将会把点击点周围做10倍放大。确保去点击集合的边缘,因为所有有趣的效果都发生在那儿。下图是我对集合左下边放大五次后的结果。

    另外,可以通过按键盘上的'c'键来变换图中颜色分布。下图是同一区域 使用了'summer'颜色分布的效果。

    在这些集合中有一个 producer/consumer 模式的标准实现。首先,我启动那些consumer任务.这些任务在producer任务生成数据之前,处于数据等待状态。(稍后我会展示一些producer 和 consumer的代码).启动consumer任务后,紧接着启动producer任务。每个producer任务执行完毕,consumer任务都会对其产生的数据进行所需的处理。在我的 曼德勃罗集 例子中,每个producer任务产生一个64x64的像素块,而consumer任务会将这些一块块的数据呈现出来。

    我用并行任务库(TPL)中的Task类来构建producer和consumer任务。任务类提供在线程中独立运行单位工作的抽象。在本例中,使用TaskFactory类创建和启动任务。TPL处理负载平衡,线程运行计划和任务附加(稍后会讨论)。该库(TPL)由常见的ThreadPool和Thread类构建,提供通用功能的抽象。在 并行计算研发中心 你可以了解更多关于.net中并行计算的内容。

    实现producer 任务

    即使首次编码使用consumer任务,但我发现有了producer任务的说明很容易上手.producer任务应当为 曼德勃罗集 生成一个64x64的颜色块。颜色块及一些支持信息必须放到共享集合。下列代码就是创建色块网格值的:

    // You can download the full source code at:
     
    // http://code.msdn.microsoft.com/DevCenterSamples
     
    // Define a couple needed structures:
     
    private struct Coord
     
    {
     
        public int X;
     
        public int Y;
     
        public int Z;
     
    }
     
    private class ImageRegion
     
    {
     
        public Int32Rect region;
     
        public List<Coord> values;
     
    }
     
    // The following is a portion of the UpdateBackingStore() method
     
    // from the sample. The DisplayTiles() method is explained later in this article,
     
    // in the Implementing the Consumer section.
     
    var results = new BlockingCollection<ImageRegion>();
     
    Task.Factory.StartNew(() => DisplayTiles(results, context));
     
    // Grids are 64 by 64:
     
    List<Task> tasks = new List<Task>();
     
    for (int yIndex = 0; yIndex < bitmap.PixelHeight; yIndex += 64)
     
        for (int xIndex = 0; xIndex < bitmap.PixelWidth; xIndex += 64)
     
        {
     
            // remember the lazy eval:
     
            var x = xIndex;
     
            var y = yIndex;
     
            var compute = Task.Factory.StartNew(() =>
     
                results.Add(
     
                // GenerateGrid() is not discussed in the article.
     
                // It generates one region of pixels. You can
     
                // look at the project for more details.
     
                GenerateGrid(minX + scale * x, minY + scale * y,
     
                Math.Min(64, width - x), Math.Min(64, height - y), 
     
                x, y, scale)
     
                ));
     
            tasks.Add(compute);
     
        }
    


    这段代码首先创建一个blocking collection 用来保存图形区域数据。之后创建了一批任务,这批任务负责计算为拼凑图形所用的每个色块相关样点颜色值。单个任务返回一个色块所有像素颜色值,同时还包括一些方便在WriteableBitmap 上的正确位置绘制色块的信息。

    此处要注意,我特意在使用计算颜色块的背景任务前创建了循环变量(xIndex and yIndex)的副本。(见上列示例代码中的注释。)任务方法是一个lambda表达式,为了任务的执行表达式会捕获一些局部变量。因为运算中用到的多数变量不会改变,所以这些捕获变量的问题不大。然后,xIndex和yIndex值却会在每个任务创建后变化。当一个任务运行后,将会检查xIndex和yIndex的当前值,而此时的值与任务创建时已经不同了。这样意味着如果没有这些变量副本,这些没有立即执行的任务将生成错误数据了。如果就本例而言,你会看到一些区域没有计算。其它区域可能会多次计算。而这将会在图像中留下一些空洞。如果你使用lambda表达式构造任务执行的委托,一定要注意这个问题。

    同时,我使用了BlockingCollection<T>的Add方法,而且调用范围内并未使用任何方式的lock语句。BlockingCollection<T>类像System.Collections.Concurrent命名空间下其它集合类型一样,提供了在其Add与remove相关方法中提供了lock功能。访问这类集合时不需要创建自己的锁定机制。

    Consumer的实现

    Consumer任务负责绘制每个producer任务创建的色点。BlockingCollection 有个方法GetConsumingEnumerable,使用该方法调用producer产生的数据将会非常轻松,感觉就像在一个单线程应用中一样。

    // You can download the full source code at:
     
    // http://code.msdn.microsoft.com/DevCenterSamples
     
    private void DisplayTiles(BlockingCollection<ImageRegion> results,
     
        TaskScheduler context)
     
    {
     
        foreach (var result in results.GetConsumingEnumerable())
     
        {
     
            var thisItem = result;
     
            Task.Factory.StartNew(() =>
     
            {
     
                foreach (var element in thisItem.values)
     
                {
     
                    zValues[element.X, element.Y] = element.Z;
     
                    pixels[element.X + element.Y * bitmap.PixelWidth] = 
     
                        // GetPixel() translates the Mandelbrot set value to a color.
     
                        fromColor(GetPixel(element.Z));
     
                }
     
                bitmap.WritePixels(thisItem.region, pixels, bitmap.PixelWidth * 4, 
     
                    thisItem.region.X, thisItem.region.Y);
     
            }, CancellationToken.None, TaskCreationOptions.None,
     
                context);
     
        }
     
    }
    


    神奇的GetConsumingEnumerable方法:如果集合为空会发生什么?它是如何知道producer任务何时完成了?当然神奇是有原因的,全在BlockingCollection<T>的代码实现中。使用MoveNext获取数据时,如果没有成功获取Consumer线程会等待。内部实现细节可能会变,但是比起Thread.Sleep方法来要复杂且高效的多。

    BlockingCollection<T>也包含一些API,可以用来指定何时所有的producer任务都完成了。如果所有producer 任务把结果存入BlockingCollection<T>,调用CompleteAdding方法,通知BlockingCollection<T>所有数据已生成。此后,一旦枚举完所有已存在数据,再调用MoveNext将不会再等待新的数据生成了,而是直接返回false.

    通知集合所有producer任务完成

    下面来到使用using the BlockingCollection<T>实现Producer / Consumer模式的最后一步:
    编写附加任务通知blocking集合所有任务已经完成。当所有producer任务完成时使用指定的方法Task.Factory.ContinueWhenAll.这段代码中,我会标识BlockingCollection<T>为已完成,通过调用CompleteAdding.同时,可以安全地释放所有producer任务(毕竟他们已经完成了)。

    // You can download the full source code at:
     
    // http://code.msdn.microsoft.com/DevCenterSamples
     
    // This is another snippet from the UpdateBackingStore() method.
     
    Task.Factory.ContinueWhenAll(tasks.ToArray(),
     
        result => 
     
            {
     
                results.CompleteAdding();
     
                foreach (var task in tasks)
     
                    task.Dispose();
     
            },
     
            CancellationToken.None, TaskContinuationOptions.None, context);
    


    BlockingCollection<T>类提供了一对属性帮助你更好的控制应用的相关行为。通过属性IsAddingCompleted可知道是否所有期望的结果都已添加进集合了(因为CompleteAdding方法的调用,集合可以决定该属性的值)。通过属性IsCompleted可知道是否所有数据均已创建完且已经被使用了(如果CompleteAdding方法已调用,且集合已为空)。所以可知:只要IsCompleted 为真IsAddingCompleted 就一定也返回真。

    当然,System.Collections.Concurrent当中的集合类还有更多其它特性。例如你可以指定BlockingCollection<T>的最大容量,一旦设置了该容量producers集合会阻塞尝试添加超出容量限制的内容到集合中。如果指定了最大容量,你可以使用TryAdd方法向一个满了的集合中添加内容而不受阻碍。

    另外,每个集合类都有一个Try<something>方法用来从集合中移除内容。该方法在不同集合类中命名有些不同:如 TryDequeue是ConcurrentQueue<T>集合类中的对应方法,TryPop是ConcurrentStack<T>中的对应方法 等。

    结论

    多线程安全集合类型为实现producer/consumer模式提供了阻塞与限制的标准机制。ConsumingEnumerable枚举方法为数据还未创建完成前的consumer线程阻塞提供了标准实现。通过设置容量的方式也限制了producer线程不会超过consumer线程.使用相关集合类实现Producer/Consumer模式你只需要写三个小的代码段。

    • producer任务 向集合中添加一个元素(数据)。
    • consumer任务使用GetConsumingEnumerable方法处理每一个可用的数据结果。
    • 扩展任务会在所有producer任务完成相关数据生成工作后标识。

    通过使用System.Concurrent.Collections下的那些实现了通用功能的集合类,再加上三小段你的代码就在多线程开发中实现了Producer/Consumer模式。

    展开全文
  • 在开发C/C++多线程程序时,STL集合类是我们经常用到的类,比如vector. 而C/C++的这些集合类并没有同步版本,所以在多线程访问时,如果某个线程正在修改集合类A, 而其他线程正在访问A,那么会造成数据冲突,导致程序抛...
  • Java 多线程(十一)JDK 同步集合

    千次阅读 2013-03-20 13:34:51
    Java 多线程 系列文章目录: Java 多线程(一)线程间的互斥和同步通信 Java 多线程(二)同步线程分组问题 Java 多线程(三)线程池入门 Callable 和 Future Java 多线程(四)ThreadPoolExecutor 线程池各参数...
  • 集合是编程最常用的数据结构。而谈到并发,几乎总是离不开集合这类高级数据结构的支持。比如两个线程需要同时访问一个中间临界区(Queue),比如常会用缓存作为外部文件的副本(HashMap)。这篇文章主要分析jdk1.5...
  • java多线程创建创建线程的方式Runnable和Callable的区别Thread类的start()和run()方法有什么区别?什么导致线程阻塞?3. 多线程同步和锁怎么检测一个线程是否持有对象监视器Condition?4. 线程池CyclicBarrier和...
  • synchronized 实际上是对访问修改共享变量的代码块进行加互斥锁,线程对synchronized代码块的访问时,某一时刻仅仅有一个线程在访问和修改代码块的内 容(加锁),其他所有的线程等待该线程离开代码块时(释放...
  • 多线程中,如果要并发的修改一个数据结构,那么很有可能会破坏这个数据结构。例如,一个线程可能要向一个散列表插入一个元素,假如在调整各个桶之间的链接关系时剥夺了控制权,而此时正好有另外一个线程正在...
  • Java多线程共享变量控制

    千次阅读 2017-09-07 15:39:48
    线程同时对主内存的一个共享变量进行读取和修改时,首先会读取这个变量到自己的工作内存成为一个副本,对这个副本进行改动之后,再更新回主内存变量所在的地方。 (由于CPU时间片是以线程为最小单位
  • Java多线程:同步集合与同步锁

    千次阅读 2018-10-14 21:58:34
    同步集合多线程开发扮演非常重要的角色,本文介绍些常用但忽略的同步集合。 CopyOnWriteArrayList Copy-On-Write是一种用于程序设计的优化策略,基本思路是多个线程共享同一个列表,当某个线程想要修改这个...
  • Java的多线程之线程安全的集合

    千次阅读 2016-02-15 18:18:34
     如果多线程要并发地修改一个数据结构,例如散列表,那么很容易会破坏这个数据结构。例如,一个线程可能要向表插入一个新元素。加入在调整散列表各个桶之间的链接关系的过程剥夺了控制权。如果另一个线程也...
  • java多线程--集合并发

    千次阅读 2021-02-08 10:56:11
    但是这个代码在多线程情况下就会出 java.lang.ArrayIndexOutOfBoundsException 1.2 为什么呢? 如下测试代码 @Test public void testSynchronizedList() throws Exception { long fisrtTime = System
  • 多线程私有资源和共享资源

    千次阅读 2014-03-18 20:34:08
    一、线程概念  线程是操作系统能够进行运算调度的最小单位。...在Unix System V及SunOS称为轻量进程(lightweight processes),但轻量进程更指内核线程(kernel thread),而把用户线程(use
  • Java多线程学习(吐血超详细总结)

    万次阅读 多人点赞 2015-03-14 13:13:17
    本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。
  • Java多线程超详解

    万次阅读 多人点赞 2019-06-11 01:00:30
    随着计算机的配置越来越高,我们需要将进程进一步优化,细分为线程,充分提高图形化界面的多线程的开发。这就要求对线程的掌握很彻底。 那么话不多说,今天本帅将记录自己线程的学习。 线程的相关API //获取当前...
  • 多线程之间共享哪些资源?

    千次阅读 2018-10-20 23:59:16
    同一进程间的线程究竟共享哪些资源呢,而又各自独享哪些资源呢? 共享的资源有 a. 堆 由于堆是在进程空间开辟出来的,所以它是理所当然地被共享的;因此new出来的都是共享的(16位平台上分全局堆和局部堆,局部...
  • java 程序怎么保证多线程的运行安全? 线程的安全性问题体现在: 原子性:一个或者多个操作在 CPU 执行的过程中断的特性 可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到 有序性:程序...
  • Android多线程:你必须要了解的多线程基础知识汇总

    千次阅读 多人点赞 2019-05-13 08:59:23
    多线程的应用在开发非常常见 今天,我将献上一份全面 & 详细的多线程基础知识汇总,希望你们喜欢。 目录 1. 线程 - 介绍 1.1 定义 一个基本的CPU执行单元 & 程序执行流的最小单元 比进程更小的可...
  • 多线程

    千次阅读 2016-07-11 18:43:09
    1 概述2 Runnable为了实现多线程共享同一段代码,一般将共享代码放在runnable执行,然后new一个runnable出来,给3个thread共享运行。3 interrupted可以在 Thread 对象上调用 isInterrupted()方法来检查任何线程的...
  • Java多线程

    千次阅读 2015-06-20 10:42:20
    Windows等操作系统均支持多线程进程的并发处理机制。操作系统支持多线程,使多个程序能够并发执行,以改善资源使用率和提高系统效率;操作系统支持多线程,能够减少程序并发时所付出的时间和空间开销,使得开发粒度...
  • android多线程----同步集合

    千次阅读 2016-05-10 17:57:51
    线程共享同一个列表,当某个线程想要修改这个列表的元素时,会把列表的元素Copy一份,然后进行修改,修改完成之后在在将新的元素设置给这个列表,这是一种懒惰策略。这样做的好处是我们可以对CopyOnWrite容器...
  • 我说我懂多线程,面试官立马给我发了offer

    万次阅读 多人点赞 2020-04-07 09:24:52
    之前我还整理过在我当时校招经常问到的多线程面试题目: 多线程了解多少啊?使用多线程会有什么问题?你是怎么理解“线程安全”的? 如果我现在想要某个操作等待线程结束之后才执行,有什么方法可以实现?为什么要...
  •  所谓线程范围内共享数据,即对于相同的程序代码,个模块在同一个线程中运行时要共享一份数据,而在另外线程中运行时又共享另外一份数据,  API中为我们提供了一个操作线程范围内共享数据的类ThreadLocal,对于...
  • Java集合多线程、反射和Spring框架总结,源码解析

    千次阅读 多人点赞 2020-07-29 15:54:09
    Java集合多线程、反射和Spring框架总结,源码解析 一、集合 - 通过不同的数据结构存储以及操作数据的工具 1.1 Collection 1.1.1 ArrayList、Vector 1.1.1.1 底层原理 ArrayList和Vector底层都是由动态数组实现的 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 157,327
精华内容 62,930
关键字:

多线程中集合被共享吗