您的位置:首页 > 编程语言 > Java开发

java 同步与异步的区别

2017-07-24 16:33 204 查看
同步就是许多线程同时用一个资源啥的哦,一个在用别的就要等,异步就相反了,可以不用等待
下面这是人家的话:
同步:发送一个请求,等待返回,然后再发送下一个请求
异步:发送一个请求,不等待返回,随时可以再发送下一个请求

同步可以避免出现死锁,读脏数据的发生,一般共享某一资源的时候用,如果每个人都有修改权限,同时修改一个文件,有可能使一个人读取另一个人已经删除的内容,就会出错,同步就会按顺序来修改。
异步则是可以提高效率了,现在cpu都是双核,四核,异步处理的话可以同时做多项工作,当然必须保证是可以并发处理的。
这些都是对的。
同步和异步最大的区别就在于。一个需要等待,一个不需要等待。
比如广播,就是一个异步例子。发起者不关心接收者的状态。不需要等待接收者的返回信息
电话,就是一个同步例子。发起者需要等待接收者,接通电话后,通信才开始。需要等待接收者的返回信息
如果数据将在线程间共享.例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取.     当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率.

 
    Java同步:
    基本概念:
    每个Object都会有1个锁.
    同步就是串行使用一些资源.
    (说明:以下有些例子为了突出重点,省略了不必要的代码.非凡是省掉了一些成员变量,就是需要同步的对象.)
    1. 多线程中对共享、可变的数据进行同步.
    对于函数中的局部变量没必要进行同步.
    对于不可变数据,也没必要进行同步.
    多线程中访问共享可变数据才有必要.
    2. 单个线程中可以使用synchronized,而且可以嵌套,但无意义.
    class Test {
    public static void main(String[] args) {
    Test t = new Test();
    synchronized(t) {
    synchronized(t) {
    System.out.println("ok!");
    }
    }
    }
    }
    3. 对象实例的锁
    class Test{
    public synchronized void f1(){
    //do something here
    }
    public void f2(){
    synchronized(this){
    //do something here
    }
    }
    }
    上面的f1()和f2()效果一致, synchronized取得的锁都是Test某个实列(this)的锁.
    比如: Test t = new Test();
    线程A调用t.f2()时, 线程B无法进入t.f1(),直到t.f2()结束.
    作用: 多线程中访问Test的同一个实例的同步方法时会进行同步.
    4. class的锁
    class Test{
    final static Object o= new Object();
    public static synchronized void f1(){
    //do something here
    }
    public static void f2(){
    synchronized(Test.class){
    //do something here
    }
    }
    public static void f3(){
    try {
    synchronized (Class.forName("Test")) {
    //do something here
    }
    }
    catch (ClassNotFoundException ex) {
    }
    }
    public static void g(){
    synchronized(o){
    //do something here
    }
    }
    }
    上面f1(),f2(),f3(),g()效果一致
    f1(),f2(),f3()中synchronized取得的锁都是Test.class的锁.
    g()是自己产生一个对象o,利用o的锁做同步
    作用: 多线程中访问此类或此类任一个实例的同步方法时都会同步. singleton模式lazily initializing属于此类.
    5. static method
    class Test{
    private static int v = 0;
    public static void f1(){
    //do something, 但函数中没用用到v
    }
    public synchronized static void f2(){
    //do something, 函数中对v进行了读/写.
    }
    }
    多线程中使用Test的某个实列时,
    (1) f1()是线程安全的,不需要同步
    (2) f2()这个静态方法中使用了函数外静态变量,所以需要同步.
     Java异步:
    一.    它要能适应不同类型的请求:
    本节用 makeString来说明要求有返回值的请求.用displayString来说明不需要返回值的请求.
    二.    要能同时并发处理多个请求,并能按一定机制调度:
    本节将用一个队列来存放请求,所以只能按FIFO机制调度,你可以改用LinkedList,就可以简单实现一个优先级(优先级高的addFirst,低的addLast).
    三.    有能力将调用的边界从线程扩展到机器间(RMI)
    四.    分离过度耦合,如分离调用句柄(取货凭证)和真实数据的实现.分离调用和执行的过程,可以尽快地将调返回.
    现在看具体的实现:
    public interface Axman {
    Result resultTest(int count,char c);
    void noResultTest(String str);
    }
    这个接口有两个方法要实现,就是有返回值的调用resultTest和不需要返回值的调用
    noResultTest, 我们把这个接口用一个代理类来实现,目的是将方法调用转化为对象,这样就可以将多个请求(多个方法调)放到一个容器中缓存起来,然后统一处理,因为 Java不支持方法指针,所以把方法调用转换为对象,然后在这个对象上统一执行它们的方法,不仅可以做到异步处理,而且可以将代表方法调用的请求对象序列化后通过网络传递到另一个机器上执行(RMI).这也是Java回调机制最有力的实现.
    一个简单的例子.
    如果 1: 做A
    如果 2: 做B
    如果 3: 做C
    如果有1000个情况,你不至于用1000个case吧?以后再增加呢?
    所以如果C/C++程序员,会这样实现: (c和c++定义结构不同)
    type define struct MyStruct{
    int mark;
    (*fn) ();
    } MyList;
    然后你可以声明这个结构数据:
    {1,A,
    2,B
    3,C
    }
    做一个循环:
    for(i=0;i<length;i++) {
    if(数据组[i].mark == 传入的值) (数据组[i].*fn)();
    }
    简单说c/c++中将要被调用的涵数可以被保存起来,然后去访问,调用,而Java中,我们无法将一个方法保存,除了直接调用,所以将要调用的方法用子类来实现,然后把这些子类实例保存起来,然后在这些子类的实现上调用方法:
    interface My{
    void test();
    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: