java同步异步的区别

同步

同步就是当A请求一个资源的时候,这个资源正在被B使用,那么A就必须要等待,等到B使用完了A才能请求到。

异步

异步就是当A请求一个资源的时候,这个资源正在被B使用,A不需要等也可以请求到

特点

所以从安全的角度出发,同步是安全的保险的,异步是不安全的,容易导致死锁,一个线程死掉就会导致整个进程崩溃,但是呢没有同步机制的话性能是会有提升的

线程池

在计算机中任何资源的创建,包括线程,都需要消耗系统资源。在Web服务中,对于web服务器的响应速度必须要快,这就容不得每次在用户提交请求之后再去创建线程再去提供服务。为了减少用户的等待时间,线程必须是预先创建的,放在线程池里面,线程池可以用HashTable这种数据结构与来实现,看了Apach HTTP服务器的线程池的源代码,用的就是HashTable,key用线程对象,value用ControlRunnable,ControlRunnable是线程池中唯一能干活的线程,是它指派线程池中的线程对外提供服务。出于安全的考虑ApachHTTP服务器的线程池它是同步的。听说weblogic有异步只是听说只是听说只是听说

关键字

thread(线程)、thread-safe(线程安全)、intercurrent(并发)                                                              synchronized(同步的)、asynchronized(异步的)、                                                                          volatile(易变的)、atomic(原子的)、share(共享)

同步,异步的时机以及怎么样做

如果要跨越线程维护正确的可见性,然后几个线程之间都用了同一个非final变量,就必须使用synchronized(或者volatile)用来确保一个线程可以看见另一个线程的操作做的更改     

为了在线程之间进行可靠的通信,也为了互斥访问,所以同步是必须的。这归因于java语言规范的内存模范,它规定了:一个线程所做的变化何时以及如何变成对其它线程可见。

因为多线程将异步行为引进了程序,所以在需要同步时,必须有一种方法强制进行。例如:如果2个线程想要通信并且共享一个复杂数据结构,如链表,此时需要确保它们互不冲突,也就是必须阻止B线程 在A线程读数据的过程中向链表里面写数据(A获得了锁,B必须等A释放了该锁)            为了达到这个目的,java在一个旧的进程同步模型----监控器(Monitor)的基础上实现了一个巧妙的方案:监控器是一个控制机制,可以认为是一个只能容纳一个线程的盒子,一旦一个线程进入监控器,其他的线程就必须等待,直到那个线程退出监控为止。通过这种方式,一个监控器可以保证共享资源在同一时刻只可被一个线程使用。这种方式称之为同步。(一旦一个线程进入一个实例的任何同步方法,别的线程将不能进入该同一实例的其他同步方法,但是该实例的非同步方法仍然能够被调用)

同步和多线程的关系:没有多线程的环境就不需要同步;有多线程也不一定需要同步。

锁提供了两种主要特性:互斥(mutual exclusion)和可见性(visibility) 

互斥就是只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据

可见性要更加复杂一些,他必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的——如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题

为了防止多个线程并发对同一数据的修改,所以需要同步,否则会造成数据不一致   (就是所谓 的线程安全。 Java集合里面的Hashtable和Vector是线程安全的。我们大部分的程序都不是线程安全的,因为没有进行同步,而且我们没有必要,因为大部分情况根本没有多线程环境)。

同步异步不要搞混了

举个例子:普通B/S模式(同步)AJAX技术(异步)

同步:提交请求->等待服务器处理->处理完返回 这个期间客户端浏览器不能干任何事

异步:请求通过事件触发->服务器处理(这时浏览器仍然可以做其他事情)->处理完毕

可见,此同步非彼同步——我们说的Java中的那个共享数据同步(synchronized)一个同步的对象是指行为(动作),一个同步的对象是指物质(共享数据)。

Java同步机制有四种实现方式

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() 、wait()

sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,把执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。

wait() 是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。(如果变量被声明为volatile,在每次访问时都会和主存一致;如果变量在同步方法或者同步块中被访问,当在方法或者块的入口处获得锁以及方法或者块退出时释放锁时变量被同步。)

                                

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值