论坛首页 入门技术论坛

java 同步和异步

浏览 5766 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (16) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-01-13   最后修改:2009-01-14

  我想的有点杂,先写在说。

 

1,关于线程安全,如果一个方法里面全部是局部变量,那么是没有必要同步的,也就是说它是线程安全的。也就是不必加synchronized,servelet里面的的HttpServlet就是这样,  PrintWriter out = response.getWriter();这句话中这个out流本来可以作为HttpServlet的类变量的,但是如果是那样就需要同步了,影响效率呀。

 

2,关于锁,

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的同一个实例的同步方法时会进行同步.
也就是说在f1()前面加上synchronized ,那线程在调用这个方法的时候取得了这个对象的锁,也就是t的锁,

 

其他的线程想访问t的其他同步方法,比如f2()就不行,其实这样是不好的,很多时候我们用另外实例变量来锁。

 

class Test{

  private static final Object obj=new Object();
    public synchronized void f1(){
    //do something here
    }
    public void f2(){
    synchronized(obj){
    //do something here
    }
    }
    }

 此时,如果一个线程访问f2,它拿到的是obj对象的锁,别的线程依然可以访问f1().

 

3,原子性,先看代码:

 

package com.test;



public class Test extends Thread {

  private int a = 0;

  private int b = 0;

  public static void main(String[] args) {

    Test test = new Test();

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

      Thread thread = new Thread(test, "thread-" + i);

      thread.start();

    }

  }

  public synchronized void doWrite() {

    a++;

    try {

      sleep((int)(Math.random()*100));

    }

    catch (Exception e) {

    }

    b++;

    try {

       sleep((int)(Math.random()*100));

    }

    catch (Exception e) {

    }

  }

  public synchronized void print() {

    System.out.println("" + Thread.currentThread().getName() + ":a:" + a);

    System.out.println("" + Thread.currentThread().getName() + ":b:" + b);

  }

  public void run() {
     f();
   
  }

  public   synchronized  void f() {
    for (int i = 0; i < 5; i++) {

      doWrite();

      print();

    }
  }

}

 

 

输出结果:

thread-0:a:1
thread-0:b:1
thread-0:a:2
thread-0:b:2
thread-0:a:3
thread-0:b:3
thread-0:a:4
thread-0:b:4
thread-0:a:5
thread-0:b:5
thread-1:a:6
thread-1:b:6
thread-1:a:7
thread-1:b:7
thread-1:a:8
thread-1:b:8
thread-1:a:9
thread-1:b:9
thread-1:a:10
thread-1:b:10
thread-2:a:11
thread-2:b:11
thread-2:a:12
thread-2:b:12
thread-2:a:13
thread-2:b:13
thread-2:a:14
thread-2:b:14
thread-2:a:15
thread-2:b:15
thread-3:a:16
thread-3:b:16
thread-3:a:17
thread-3:b:17
thread-3:a:18
thread-3:b:18
thread-3:a:19
thread-3:b:19
thread-3:a:20
thread-3:b:20
thread-4:a:21
thread-4:b:21
thread-4:a:22
thread-4:b:22
thread-4:a:23
thread-4:b:23
thread-4:a:24
thread-4:b:24
thread-4:a:25
thread-4:b:25
thread-5:a:26
thread-5:b:26
thread-5:a:27
thread-5:b:27
thread-5:a:28
thread-5:b:28
thread-5:a:29
thread-5:b:29
thread-5:a:30
thread-5:b:30
thread-6:a:31
thread-6:b:31
thread-6:a:32
thread-6:b:32
thread-6:a:33
thread-6:b:33
thread-6:a:34
thread-6:b:34
thread-6:a:35
thread-6:b:35
thread-7:a:36
thread-7:b:36
thread-7:a:37
thread-7:b:37
thread-7:a:38
thread-7:b:38
thread-7:a:39
thread-7:b:39
thread-7:a:40
thread-7:b:40
thread-8:a:41
thread-8:b:41
thread-8:a:42
thread-8:b:42
thread-8:a:43
thread-8:b:43
thread-8:a:44
thread-8:b:44
thread-8:a:45
thread-8:b:45
thread-9:a:46
thread-9:b:46
thread-9:a:47
thread-9:b:47
thread-9:a:48
thread-9:b:48
thread-9:a:49
thread-9:b:49
thread-9:a:50
thread-9:b:50

 我们可以看到是很标准的输出。

 

我们在run方法里面改点东西:

 

package com.test;



public class Test extends Thread {

  private int a = 0;

  private int b = 0;

  public static void main(String[] args) {

    Test test = new Test();

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

      Thread thread = new Thread(test, "thread-" + i);

      thread.start();

    }

  }

  public synchronized void doWrite() {

    a++;

    try {

      sleep((int)(Math.random()*100));

    }

    catch (Exception e) {

    }

    b++;

    try {

       sleep((int)(Math.random()*100));

    }

    catch (Exception e) {

    }

  }

  public synchronized void print() {

    System.out.println("" + Thread.currentThread().getName() + ":a:" + a);

    System.out.println("" + Thread.currentThread().getName() + ":b:" + b);

  }

  public void run() {
    for (int i = 0; i < 5; i++) {

      doWrite();

      print();

    }
   
  }

  

}

 

输出的结果就不确定了:

 

thread-0:a:10
thread-0:b:10
thread-1:a:10
thread-1:b:10
thread-2:a:10
thread-2:b:10
thread-3:a:10
thread-3:b:10
thread-4:a:10
thread-4:b:10
thread-5:a:10
thread-5:b:10
thread-6:a:10
thread-6:b:10
thread-7:a:10
thread-7:b:10
thread-8:a:10
thread-8:b:10
thread-9:a:10
thread-9:b:10
thread-0:a:20
thread-0:b:20
thread-1:a:20
thread-1:b:20
thread-2:a:20
thread-2:b:20
thread-3:a:20
thread-3:b:20
thread-4:a:20
thread-4:b:20
thread-5:a:20
thread-5:b:20
thread-6:a:20
thread-6:b:20
thread-7:a:20
thread-7:b:20
thread-8:a:20
thread-8:b:20
thread-9:a:20
thread-9:b:20
thread-0:a:30
thread-0:b:30
thread-1:a:30
thread-1:b:30
thread-2:a:30
thread-2:b:30
thread-3:a:30
thread-3:b:30
thread-4:a:30
thread-4:b:30
thread-5:a:30
thread-5:b:30
thread-6:a:30
thread-6:b:30
thread-7:a:30
thread-7:b:30
thread-8:a:30
thread-8:b:30
thread-9:a:30
thread-9:b:30
thread-0:a:40
thread-0:b:40
thread-1:a:40
thread-1:b:40
thread-2:a:40
thread-2:b:40
thread-3:a:40
thread-3:b:40
thread-4:a:40
thread-4:b:40
thread-5:a:40
thread-5:b:40
thread-6:a:40
thread-6:b:40
thread-7:a:40
thread-7:b:40
thread-8:a:40
thread-8:b:40
thread-9:a:40
thread-9:b:40
thread-0:a:50
thread-0:b:50
thread-1:a:50
thread-1:b:50
thread-2:a:50
thread-2:b:50
thread-3:a:50
thread-3:b:50
thread-4:a:50
thread-4:b:50
thread-5:a:50
thread-5:b:50
thread-6:a:50
thread-6:b:50
thread-7:a:50
thread-7:b:50
thread-8:a:50
thread-8:b:50
thread-9:a:50
thread-9:b:50

 

 

我们的目的就是要 完数据后在输出,所以应该确保这个过程的原子性。直接写在run方法里面就没能确保原子性。

先写到这,以后在加吧。

   发表时间:2009-01-13  
cy729215495 写道
我们的目的就是要 完数据后在输出,所以应该确保这个过程的原子性。直接写在run方法里面就没能确保原子性

1.原子性?java.util.concurrent.atomic.*多得很!
2.run方法里面就没能确保原子性?java.util.concurrent.locks.* or synchronized(...){...}
0 请登录后投票
   发表时间:2009-01-13  
gembler 写道
cy729215495 写道
我们的目的就是要 完数据后在输出,所以应该确保这个过程的原子性。直接写在run方法里面就没能确保原子性

1.原子性?java.util.concurrent.atomic.*多得很!
2.run方法里面就没能确保原子性?java.util.concurrent.locks.* or synchronized(...){...}

同意,建议lz去看看O‘系列丛书的Java线程。
0 请登录后投票
   发表时间:2009-01-14  
gembler 写道
cy729215495 写道
我们的目的就是要 写完数据后在输出,所以应该确保这个过程的原子性。直接写在run方法里面就没能确保原子性

1.原子性?java.util.concurrent.atomic.*多得很!
2.run方法里面就没能确保原子性?java.util.concurrent.locks.* or synchronized(...){...}


我的意思是这个过程,这个过程就是”写完数据后在输出“,拜托你提点有意义的意见,并说出想法,还有二楼的,光看那上面的书好像不够吧。现在很多人根本就不懂多线程(web服务器运行后挂掉了,连接没关闭出错,这样的帖子屡见不鲜),包括我自己,也不是很清楚。本来我放在我的博客里面了可以生成电子书了,等公司放假了去打印,7分钱一张,很方便,我之所以把文章发表,一来是总结下自己的经验,二来可以温故下,三可以让别人看我的文章学点东西,四是也可以让读者提出有意义的意见。
0 请登录后投票
   发表时间:2009-01-14   最后修改:2009-01-14
gembler 写道
cy729215495 写道
我们的目的就是要 完数据后在输出,所以应该确保这个过程的原子性。直接写在run方法里面就没能确保原子性

1.原子性?java.util.concurrent.atomic.*多得很!
2.run方法里面就没能确保原子性?java.util.concurrent.locks.* or synchronized(...){...}

难道你觉得不比你的代码更有意义?
cy729215495 写道
public synchronized void doWrite() {//...}

  public synchronized void print() {//...}

  public void run() {
     f();
  }

  public   synchronized  void f() {
    for (int i = 0; i < 5; i++) {
      doWrite();
      print();
    }
  }

难道你不觉得你这样设计很有问题?
cy729215495 写道
我之所以把文章发表,一来是总结下自己的经验,二来可以温故下,三可以让别人看我的文章学点东西四是也可以让读者提出有意义的意见

3.你知道会误认子弟的不
4.有意思的意见?不清楚你是怎么样定位“有意义的意见”
0 请登录后投票
   发表时间:2009-01-14  
也好 也好 也好
0 请登录后投票
   发表时间:2009-01-16  
楼主的措辞的确让人很费解。

或者说思维不是那么有条理,反正看了的结果就是觉得像是翻译不好的外文书。
0 请登录后投票
   发表时间:2009-01-17  
难道就没有人注意第一句话,“我想的有点杂,先写在说。”??????????
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics