Java 同步&&异步 || 阻塞&&非阻塞 || 线程安全&&线程不安全 概念解析

1.Java同步&&异步

    同步使用: 如果数据将在线程间共享.例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取.

    异步使用当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率.

         举个例子:

普通B/S模式(同步)AJAX技术(异步)  
             同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事  
             异步:   请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕
        生活案例:
            同步:你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。  
            异步:你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。   
        通讯:   
           同步:发送一个请求,等待返回,然后再发送下一个请求  
           异步:发送一个请求,不等待返回,随时可以再发送下一个请求   
            
   java实现同步的方式:

    Java同步机制有4种实现方式:  
    ① ThreadLocal ② synchronized( ) ③ wait() 与 notify() ④ volatile   
    目的:都是为了解决多线程中的对同一变量的访问冲突 

 ThreadLocal:  
       ThreadLocal 保证不同线程拥有不同实例,相同线程一定拥有相同的实例,即为每一个使用该变量的线程提供一个该变量值的副本,每一个线程都可以独立改变自己的副本,而不是与其它线程的副本冲突。  
          优势:提供了线程安全的共享对象   
与其它同步机制的区别:同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信;而 ThreadLocal 是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源,这样当然不需要多个线程进行同步了。  
 volatile  
        volatile 修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。  
          优势:这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。因为Java 语言规范中指出,为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。而 volatile 关键字就是提示 VM :对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。  
          使用技巧:在两个或者更多的线程访问的成员变量上使用 volatile 。当要访问的变量已在 synchronized 代码块中,或者为常量时,不必使用。  
        线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B。只在某些动作时才进行A和B的同步,因此存在A和B不一致的情况。volatile就是用来避免这种情况的。 volatile告诉jvm,它所修饰的变量不保留拷贝,直接访问主内存中的(读操作多时使用较好;线程间需要通信,本条做不到)。Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。 您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:对变量的写操作不依赖于当前值;该变量没有包含在具有其他变量的不变式中。     
   sleep() vs wait()  
        sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,把执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。  
        wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。   
(如果变量被声明为volatile,在每次访问时都会和主存一致;如果变量在同步方法或者同步块中被访问,当在方法或者块的入口处获得锁以及方法或者块退出时释放锁时变量被同步。)

  同步和异步仅仅是关于所关注的消息如何通知的机制,而不是处理消息的机制.也就是说,同步的情况下,是由处理消息者自己去等待消息是否被触发,而异步的情况下是由触发机制来通知处理消息者。

2.Java阻塞&&非阻塞

     阻塞:是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。 

    非阻塞:在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

3.Java线程安全和线程不安全

    线程安全:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。线程安全问题大部分是由全局变量及静态变量引起的。

   线程不安全若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

4.比较

    阻塞有一个很明显的特征就是Blocking,有了这个特征才叫做阻塞。在java程序中的线程通常处于Blocking状态,同步并不是这样的,同步通常是指步骤需要一步步来完成,就按常规的代码一条条的执行下去。相对于阻塞状态,同步的线程应当处于Running状态。线程处于Blocking状态就差不多可以看成是休眠了,就是什么也没法做,只有等待信号将他唤醒而Running状态的线程是活跃的。在这种状态下可以去做很多的事情。

   线程安全依靠的就是同步机制。线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步。

5.常见:

   ArrayList,LinkedList线程不安全,Vector 线程安全

   HashMap线程不安全,Hashtable 线程安全 

   Stringbuilder线程不安全,Stringbuffer线程安全

6.参考资源:

http://www.blogjava.net/pengpenglin/archive/2010/03/10/315053.html

http://www.cnblogs.com/dayday-study/archive/2012/04/17/2453827.html

http://blog.csdn.net/liuliulomo/article/details/7003459

http://blog.sina.com.cn/s/blog_46fc12960100dosb.html

转载于:https://my.oschina.net/tdd/blog/345726

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值