`
zhangxiaofei13
  • 浏览: 4062 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

java基础数据结构之有条件线程安全

阅读更多
有条件线程安全.
事出于一次偶然的MS中,在问及hashmap和hashtable的时候很习惯的就说非线程安全和线程安全。却被告知有条件线程安全这一说法。
困惑之余查看了hashtable 和hashmap 的源码,
public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> 及
public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>,
  Cloneable, Serializable
在Hashtable 中每一个方法都是synchronized同步的,也就是线程安全的。
查看资料发现,早有砖家提出了有条件线程安全这一概念。
并发专家Brian Goetz将Hashtable和Vector类描述为“有条件线程安全的”。一个类难道不是线程安全就是线程不安全的吗?不幸的是,线程安全并不是一个非真即假的命题。
一个类在可以被多个线程安全调用时就是线程安全的? 这可能是大部分人理解的线程安全。
砖家提出:
·        ...可以从多个编程线程中调用,无需线程之间不必要的交互。·        ...可以同时被多个线程调用,不需要调用一方有任何操作。
下面看看vector的一个例子
import java.util.List;
import java.util.Vector;

public class VectorTest {
 List  vector= new Vector();
 public  void init() {
  for (int i=0; i<1000 ; i++) {
   vector.add(i);
  }
 }

 public  void get(int i) {
  vector.get(i);
 }

 public  void remove(int i) {
  vector.remove(i);
 }


 public void  start() {
  this.init();
  new Thread(new ListOpt(vector)).start();
  for (int i=0; i<100 ; i++) {
   new Thread(new ListOpt1(vector)).start();
  }
 }


 public static void main(String[] args) {
  VectorTest test = new VectorTest();
  test.start();
 }
 class ListOpt implements Runnable {
  private List  list;
  public ListOpt(List  list ) {
   this.list = list;
  }
  public void run() {
   try {
     for (int i=0 ;i<1000;  i++) {
      int listsize= list.size();
      System.out.println(list.get(listsize-1));
    }
     
    } catch (Exception e) {
     e.printStackTrace();
    }
  }
 }
  
  class ListOpt1 implements Runnable {
   private List  list;
   public ListOpt1(List  list ) {
    this.list = list;
   }
      public void run() {
      try {
        list.remove(list.size()-1);
       } catch (Exception e) {
        e.printStackTrace();
       }
      
   }
    
 }
   
}
‍


执行结果大家也可以预料的到的
顺利执行完成

java.lang.ArrayIndexOutOfBoundsException: Array index out of range: ***
	at java.util.Vector.get(Unknown Source)
	at VectorTest$ListOpt.run(VectorTest.java:44)
	at java.lang.Thread.run(Unknown Source)


可能有人这时候就要说,run 方法中的Vector每一个方法都是同步的,这不能作为线程不安全的依据
问题代码在于:
int listsize= list.size();
System.out.println(list.get(listsize-1));



    ‍    这一问题是由get()的前置条件是以size()的结果来定义的这一事实所带来的。只要看到这种必须使用一种方法的结果作为另一种讲法的输入条件的样式,它就是一个状态依赖,就必须保证至少在调用这两种方法期间元素的状态没有改变。一般来说,做到这一点的唯一方法在调用第一个方法之前是独占性地锁定对象,一直到调用了后一种方法以后。在上面的迭代Vector元素的例子中,需要在迭代过程中同步Vector对象。
再回过头来看看
线程安全性    类要成为线程安全的,首先必须在单线程环境中有正确的行为。如果一个类实现正确(这是说它符合规格说明的另一种方式),那么没有一种对这个类的对象的操作序列(读或者写公共字段以及调用公共方法)可以让对象处于无效状态,观察到对象处于无效状态、或者违反类的任何不可变量、前置条件或者后置条件的情况。    此外,一个类要成为线程安全的,在被多个线程访问时,不管运行时环境执行这些线程有什么样的时序安排或者交错,它必须仍然有如上所述的正确行为,并且在调用的代码中没有任何额外的同步。其效果就是,在所有线程看来,对于线程安全对象的操作是以固定的、全局一致的顺序发生的。    正确性与线程安全性之间的关系非常类似于在描述 ACID(原子性、一致性、独立性和持久性)事务时使用的一致性与独立性之间的关系:从特定线程的角度看,由不同线程所执行的对象操作是先后(虽然顺序不定)而不是并行执行的。
上面例子中的方法之间的状态依赖关系似乎破坏了整个类的一致性和独立性。

不可变   不可变的对象一定是线程安全的,并且永远也不需要额外的同步。因为一个不可变的对象只要构建正确,其外部可见状态永远也不会改变,永远也不会看到它处于不一致的状态。Java 类库中大多数基本数值类如 Integer 、 String 和 BigInteger 都是不可变的。 
线程安全   由类的规格说明所规定的约束在对象被多个线程访问时仍然有效,不管运行时环境如何排列,线程都不需要任何额外的同步。这种线程安全性保证是很严格的 -- 许多类,如 Hashtable 或者 Vector 都不能满足这种严格的定义。


所以。。。
分享到:
评论

相关推荐

    Java多线程结构_Java多线程结构_

    Java多线程结构是Java编程中的重要组成部分,它允许程序同时执行多个任务,提升系统效率。在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当自定义类继承Thread类时,...

    Java基础,Java进阶,Java数据结构,十大算法

    然后是“Java数据结构”部分,这部分主要讲解如何在Java中实现和使用各种数据结构: 1. **数组与链表**:基础数据结构,理解它们的时间复杂度和空间复杂度。 2. **栈与队列**:LIFO(后进先出)和FIFO(先进先出)...

    Java语言程序设计与数据结构(第11版)_java_

    作为基础篇,它旨在为初学者提供全面的Java编程基础,并深入讲解如何利用Java实现各种数据结构。以下是对这本书核心知识点的详细阐述: 1. **Java编程基础**:本书首先会介绍Java语言的基础语法,包括变量、常量、...

    数据结构多线程

    数据结构和多线程是计算机科学中的两个重要概念,它们在构建高效、可扩展的软件系统中发挥着关键作用。本文将深入探讨这两个主题,并结合"TabbarView"这一标签,探讨它们在实际开发中的应用。 首先,我们来理解什么...

    关于线程(java)两天的课件

    最后,线程安全的数据结构如ConcurrentHashMap、Atomic变量等,能够保证在多线程环境下正确地操作数据,提升并发性能。理解并熟练掌握这些概念和工具,是成为一名优秀的Java并发程序员必不可少的步骤。 总之,本...

    java程序 两个线程实现学生成绩的读写

    为了保证数据安全,通常我们会使用`synchronized`关键字或者`java.util.concurrent`包下的并发数据结构。写入线程会不断接收新的课程和成绩,然后将其添加到共享数据结构中。 读取线程(`ReaderThread`)则需要不断地...

    java自定义线程模型处理方法分享

    5. **线程安全的数据结构和同步机制**:在多线程环境中,数据的访问和修改需要保证线程安全。可以使用`java.util.concurrent`包中的线程安全容器,如`ConcurrentHashMap`、`BlockingQueue`等,以及`synchronized`...

    JAVA语言程序设计与数据结构第十一版基础篇答案,java语言程序设计基础篇第十版第十章答案,Java

    《JAVA语言程序设计与数据结构第十一版基础篇答案》主要涵盖了Java编程语言的基本概念、语法和数据结构的运用。本书旨在帮助初学者理解和掌握Java编程的基础知识,并通过解决实际问题来深化对数据结构的理解。以下是...

    Java集合多线程安全.docx

    线程安全指的是一个对象在多线程环境下可以被正确地访问和修改,而不会出现竞态条件或死锁等问题。 线程不安全的集合类包括: 1. `ArrayList`:它的添加、删除和修改操作不是线程安全的。例如,在多个线程同时尝试...

    Java线程详解大全

    总之,Java线程是并发编程的基础,理解和掌握线程的生命周期、实现方式和同步机制对于编写高效、安全的多线程程序至关重要。在实际应用中,根据需求选择合适的线程实现策略,并结合同步机制,可以有效地利用系统资源...

    java线程 线程学习资料 java线程教程

    - `ConcurrentHashMap`等并发集合提供了线程安全的数据结构。 - `CountDownLatch`、`CyclicBarrier`等工具类帮助解决多线程编程中的常见问题。 - **异常处理**: - 了解如何正确处理线程中抛出的异常。 #### 八、...

    Java 软件设计基础:Java线程机制

    线程不拥有系统资源,只有运行必需的一些数据结构;它与父进程的其他线程共享该进程拥有的全部资源。 多线程 多线程指在单个程序中可以同时运行多个不同的线程,执行不同的任务。这是实现并发机制的一种有效手段。...

    java 多线程交互简单范例

    1. **Producer.java**:这个文件可能包含一个生产者线程的实现,它的任务是在共享数据结构(如队列或栈)中添加元素。在多线程环境里,生产者线程可能需要等待适当的时机才能插入新元素,以免与其他线程产生冲突。 ...

    java 多线程编程指南

    Java提供了synchronized关键字来实现线程安全,它可以修饰方法或代码块,确保同一时间只有一个线程能访问特定的代码。此外,还有volatile关键字,用于确保变量的可见性和有序性,防止数据的不一致。 死锁是多线程...

    【JAVA多线程】多线程编程核心技术学习资料

    3. 线程安全的数据结构:如ConcurrentHashMap、Atomic系列类(AtomicInteger、AtomicReference等),这些类提供了在并发环境下的高效操作,避免了数据不一致的问题。 4. 守护线程(Daemon Thread):这种线程在没有...

    基于JAVA毕业设计-JAVA多线程与线程安全实践-基于Http协议的断点续传.rar

    3. 创建线程安全的数据结构来跟踪和更新下载状态,避免竞态条件。 4. 使用适当的同步机制确保在写入文件时的一致性。 5. 处理网络异常和重试策略,以应对可能的网络波动。 这个毕业设计项目提供了一个宝贵的实战...

    java基础核心学习笔记

    - 控制结构:包括条件语句(if-else)、循环(for、while、do-while)和分支结构(switch)。 - 函数(方法):Java中的函数是代码块,用于实现特定功能。函数可以返回值或不返回值。 2. **面向对象编程** - 类...

Global site tag (gtag.js) - Google Analytics