zoukankan      html  css  js  c++  java
  • 线程同步的几种手段

    在软件产品特别是大容量通信系统的研发过程中,线程安全的重要性是不言而喻的。通常我们会使用synchronized 这样的同步关键字来做线程同步.却忽略了这样做也会面临许多的问题,比如synchronized关键字同步方法代码块等同步监视器只能是对像,而不是把一段代码或是函数当作锁。如果我们的代码对同步方法的类再实例化一次的时候,或者代码不注意引起这个类多次实例化了的时候并不能做到线程同步.(当然我们可以通过类同步来纠正,但是这样做无疑扩大了同步的范围,在系统并发量要求大的情况下,显然不合适)

    所以了这种同步方式在简单的场情下可能不会觉察出什么问题,但是并发量大时在性能下必然是受影响的。就个人理解而言,线程同步至少存在以下几种方式.

    1.将变量声名原子的,如AtomicInteger。值得注意的是,这个地方经常用有人误用volatile static int这样的形式来声明,这样是起不到线程安全作用的。如下面这种情况:

    public class VolatileTest {

           public volatile static int count = 0;

           public static AtomicInteger atomCount = new AtomicInteger(0);

     

           public static void increment() {

                  try {

                         Thread.sleep(1);

                  } catch (InterruptedException e) {

                         e.printStackTrace();

                  }

                  count++;

                  atomCount.getAndIncrement();

           }

     

           public static void main(String[] args) throws InterruptedException {

                  /**同时启动1000个线程,去进行count++计算,看看实际结果*/

                  for (int i = 0; i < 1000; i++) {

                         new Thread(new Runnable() {

                                @Override

                                public void run() {

                                       VolatileTest.increment();

                                }

                         }).start();

                         // Thread.sleep(2);

                  }

     

                  /**主线程休眠,尽量使得业务线程全部执行完*/

                  Thread.sleep(5000);

                  /**这里每次运行的值都有可能不同,可能为1000*/

                  System.out.println("运行结果:count=" + count);

                  /**每次结果为1000*/

                  System.out.println("运行结果:atomCount=" + atomCount.get());

           }

    }

     

     

    2.使用Semaphore控制并发:

    public class Semaphore2Test {

           /** 表示需要控制(线程同步)的资源 */

           private static int money = 100;

           private static Semaphore singal = new Semaphore(1);

     

           public static void main(String[] args) throws InterruptedException {

                  Semaphore2Test semaphoreTest = new Semaphore2Test();

                  semaphoreTest.threadSync();

           }

     

           public void threadSync() {

                  new Thread(new Runnable() {

                         @Override

                         public void run() {

                                /** 一次启动100个业务线程 */

                                for (int i = 0; i < 100; i++) {

                                       new Thread(new Runnable() {

                                              @Override

                                              public void run() {

                                                     try {

                                                            singal.acquire();

                                                     } catch (InterruptedException e1) {

                                                            e1.printStackTrace();

                                                     }

                                                     money++;

                                                     System.out.println(money);

                                                     singal.release();

                                              }

                                       }).start();

                                }

                         }

                  }).start();

           }

    }

     

    3.使用Lock控制并发线程:

    public class LockTest {

           public static int count = 0;

           public static Lock lock =new ReentrantLock();

     

           public static void increment() {

                  lock.lock();

                  try {

                         count++;

                  } catch (Exception e) {

                         e.printStackTrace();

                  }finally{

                         lock.unlock();

                  }

           }

     

           public static void main(String[] args) throws InterruptedException {

                  /**同时启动1000个线程,去进行count++计算,看看实际结果*/

                  for (int i = 0; i < 1000; i++) {

                         new Thread(new Runnable() {

                                @Override

                                public void run() {

                                       LockTest.increment();

                                }

                         }).start();

                  }

     

                  /**主线程休眠,尽量使得业务线程全部执行完*/

                  Thread.sleep(5000);

                  /**每次相同同,均为1000*/

                  System.out.println("运行结果:count=" + count);

           }

    }

     

    4.使用synchronized控制并发线程。略

  • 相关阅读:
    Visio画出的图,裁剪成固定大小再添加马赛克的方法
    单张PPT转成单张PDF的PDF文件怎么设置打印出一页纸有6页PPT
    MVC下载电子表格到本地((导出表格4-4)
    获取配置文件(导出表格4-3)
    获取随机字符串(导出表格4-2)
    ExcelHelper 电子表格帮助类(导出表格4-1)
    二、操作NPOI_从数据库中导出数据到Excel_支持.xls格式
    一、操作NPOI从Excel中导入数据到SqlServer数据库中_xls格式
    Fetch(Promise微队列) 增删改查
    C#获取枚举的描述
  • 原文地址:https://www.cnblogs.com/hnucdj/p/3556328.html
Copyright © 2011-2022 走看看