黑马程序员技术交流社区

标题: 静态同步函数,同步函数的锁问题 [打印本页]

作者: 梁航斌    时间: 2013-4-8 15:59
标题: 静态同步函数,同步函数的锁问题
本帖最后由 梁航斌 于 2013-4-9 08:18 编辑

静态同步函数,同步函数为了保险起见都用obj锁可以吗?有什么好的建议,之前视频有看,但现在又忘得差不多了。
作者: whs_nk    时间: 2013-4-8 22:06
不一定的,并发线程中与共享变量有关的程序段称为临界区。学习毕老师的视频后,我们知道java中用关键字synchronized声明一段临界区,只要该为临界区加的是同一把锁就可以实现同步的,这里是我写过的代码,读者和写者问题,经典的同步问题。请认真看下吧,希望能帮到你哦。
  1. /**
  2. * 题目:用多线程同步思想实现对某个共享缓冲区的读写操作的设计,即一旦写入数据,马上读走。
  3. * 线程同步,说白了,强调的是先后次序,也就是说必须等我这边忙完了,你那边才开始。
  4. * */
  5. public class ReaderAndWrite {

  6.         public static void main(String[] args) {
  7.                
  8.                 Buffer buffer = new Buffer();
  9.                 String[] datas = {"张三","李四","王五","赵六"};
  10.                 new writer(buffer,datas).start();
  11.                 new Reader(buffer,datas).start();
  12.         }
  13. }

  14. class Buffer{
  15.         private String data;
  16.         private boolean isNull = true;//读写线程通信的信号量,true表示缓冲区为空,可写
  17.         public  void putData(String data){
  18.                 while (!isNull) {//等待isNull为true,即等待数据被读走
  19.                         try {
  20.                                 this.wait();
  21.                         } catch (InterruptedException e) {
  22.                                 e.printStackTrace();
  23.                         }
  24.                 }
  25.                 this.data = data;//此时isNull为true,即前一个数据已被取走
  26.                 isNull = false;//将信号量设为false,表示缓冲区不为空,用以通知读进程
  27.                 notify();//唤醒等待的读线程,以进行读取刚刚存入的数据
  28.         }
  29.        
  30.         public  String getData(){
  31.                 while (isNull) {//此时若isNull为true,即无数据,则等待isNull为false,即等待写入数据
  32.                        
  33.                         try {
  34.                                 this.wait();
  35.                         } catch (InterruptedException e) {
  36.                                 e.printStackTrace();
  37.                         }
  38.                 }
  39.                 isNull = true;//将信号量设为true,表示缓冲区为空,用以通知写进程
  40.                 notify();//唤醒等待的写线程,以进行写操作
  41.                 return data;//有数据则返回当前数据
  42.         }
  43. }

  44. class writer extends Thread{
  45.         private Buffer buffer;
  46.         private String[] datas;
  47.         public writer(Buffer buffer,String[] datas) {
  48.                 this.buffer = buffer;
  49.                 this.datas = datas;
  50.         }
  51.         public  void run(){       
  52.                 //很明显,涉及到缓冲区,则可以将表示缓冲区的共享变量设为锁
  53.                 synchronized (buffer) {
  54.                         for(int i = 0;i<datas.length;i++){
  55.                                 buffer.putData(datas[i]);
  56.                                 System.out.println("写入:"+datas[i]);       
  57.                         }
  58.                 }
  59.         }
  60. }

  61. class Reader extends Thread{
  62.         private Buffer buffer;
  63.         private String[] datas;
  64.         public Reader(Buffer buffer,String[] datas) {
  65.                 this.buffer = buffer;
  66.                 this.datas = datas;
  67.         }
  68.         public void run(){
  69.                 //使用与写操作相同的缓冲区,则设置同一把锁
  70.                 synchronized (buffer) {
  71.                         for(int i = 0;i<datas.length;i++){
  72.                                 System.out.println("读取:"+buffer.getData());       
  73.                         }
  74.                 }
  75.         }
  76. }
复制代码

作者: 陈丽莉    时间: 2013-4-8 23:49
若还有问题,继续追问; 没有的话,将帖子分类改成【已解决】哦~

点进自己的帖子,编辑->标题左侧有下拉菜单->改变分类->保存~
作者: 曹宇    时间: 2013-4-8 23:59
一般锁有3个  obj  this  和类名.class
静态没有this指针  静态同步函数使用的锁就是他所在的类的   字节码文件对象
就是 类名.class  这就是静态同步函数使用的锁.
作者: 王大斌    时间: 2013-4-9 01:04
建议使用lock对象
作者: 黑马李杰    时间: 2013-4-9 07:25
函数要是想同步的话,必须保证引用的同一把锁,但是静态函数是先于构造函数加载的,所以使用本类对象不行,可以使用Object类的对象,因为Object类是唯一的,还可以用本类的字节码,因为一个类的字节码只有一份。
作者: 梁航斌    时间: 2013-4-9 08:22
whs_nk 发表于 2013-4-8 22:06
不一定的,并发线程中与共享变量有关的程序段称为临界区。学习毕老师的视频后,我们知道java中用关键字sync ...

非常感谢,很好的例子




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2