对synchronized的一个疑问

oxmll 2005-12-22 11:02:18
在LINUX中,使用spin_lock/spin_unlock来实现锁,调用时,都有一个锁名,例如spin_lock(&lock)/spin_unlock(&unlock)。
但是,在JAVA中,使用synchronized时,例如:
public synchronized read(int Length)
{
......
}
public synchronized write(char c)
{
......
}
并没有显式地指定锁名,系统怎么能判断在read时不能write呢?或者就是简单的将其处理成原子操作?如果我有两个缓冲区,都有read/write操作,这时的代码应该怎么实现呢?我对JAVA的同步不是很懂,哪位能详细的解说一下?
...全文
408 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
crazycy 2005-12-23
  • 打赏
  • 举报
回复
mark
muymuy 2005-12-23
  • 打赏
  • 举报
回复
解决办法ChDw(米)已经说了,我说说synchronized原理

Java里synchronized有三种用法,第一种是:
synchronized(obj)
{
...
}
第二种就是搂主提到的,在方法前加synchronized关键字。
第三种是static方法前加synchronized关键字。

第一种用法是对对象obj加锁,
第二种是对this对象加锁,
第三种是对改类的一个隐藏的成员变量加锁,这个变量是ClassName.class,Java里每一个类都有一个这样的变量,变量名都是class,比如:
class Test
{
static void synchronized method(){};
}
等同于:
class Test
{
static void synchronized method()
{
synchronized (Test.class)
{
}
};
}
ChDw 2005-12-22
  • 打赏
  • 举报
回复
我一般会使用notifyAll多点,只是在p中要用while而不是if来判断

另外,上面的问题不会出问题啊,系统是随机唤醒一个正在等这个对象的线程,当时不是所有等待线程
oxmll 2005-12-22
  • 打赏
  • 举报
回复
那是否意味着:
如果我需要两个信号量,例如:

static mySem sem1;
static mySem sem2;
public void init()
{
sem1 = new mySem();
sem2 = new mySem();
}
class mySem
{
int semaphore;
public mySem()
{
semaphore=0;
}

public syncronized void P()
{
semaphore--;
if(semaphore<0)
{
try
{
wait();
}catch(InterruptedException ie){}
}
}

public synchronized void V()
{
semaphore++;
if(semaphore<=0)
notify();
}
}
在使用的时候,就会出问题?是否需要将其改为notifyAll
ChDw 2005-12-22
  • 打赏
  • 举报
回复
系统随机找一个正确等待的线程,不能判断出来
oxmll 2005-12-22
  • 打赏
  • 举报
回复
还有一个问题,就是上面的P/V操作中,调用notify();系统根据什么来判断这时候唤醒的是哪一个的wait()???
enet_java 2005-12-22
  • 打赏
  • 举报
回复
今天看了也受益了
kingofhawks 2005-12-22
  • 打赏
  • 举报
回复
同意楼上,syncronized是对对象进行同步.
oxmll 2005-12-22
  • 打赏
  • 举报
回复
hehe,实际上,我把同步和互斥混淆了,synchronized是同步机制,我需要的是互斥机制,参考http://fanqiang.chinaunix.net/program/java/2001-06-08/2098.shtml:
在进行多线程编程时,经常要使用同步互斥机构,但java本身没有提供的同步互斥机构,仅提供了两个与同步互斥有关的方法:wait()和notify(),可以用来设计信号量类:mySemaphore,它是按照Dijkstra提出的计数信号量的思想设计的。

mySemaphore有两个最重要的成员方法:P()和V()。这两个方法实际就实现了信号量的P操作和V操作。具体描述如下:

public synchronized void P(){

semaphore--;

if(semaphore<0){

try{

wait();

}catch(InterruptedException ie){}

}

}

public synchronized void V(){

semaphore++;

if(semaphore<=0)

notify();

}

其中,semaphore变量记录了信号量的状态,wait()方法相当于block原语,用于阻塞线程的执行,notify()方法相当于wakeup原语,用于唤醒线程恢复运行。由于这两个方法定义为synchronized,这样java虚拟机可保证这两个方法的原子执行,从而实现了P、V操作。
ChDw 2005-12-22
  • 打赏
  • 举报
回复
那么你不应该在方法上声明synchronized ,在方法上声明 synchronized表示进入这个方法必须对这个对象加锁

你可以这样
private Object lock1 = new Object();
private Object lock2 = new Object();


public void read1(int len) {
synchronized(lock1) {
....
}
}
public void write(char ch) {
synchronized(lock1) {
....
}
}
public void read2(int len) {
synchronized(lock2) {
....
}
}
public void write2(char ch) {
synchronized(lock2) {
....
}
}

这样就没有问题
oxmll 2005-12-22
  • 打赏
  • 举报
回复
我的意思是:
public synchronized void read1(int len)
public synchronized void write1(char c)
public synchronized void read2(int len)
public synchronized void write2(char c)
实际上,要求的是在read1时,不能执行write1,但是可以执行write2,那系统怎么区分呢?
notruiyi 2005-12-22
  • 打赏
  • 举报
回复
增加一个缓冲区管理,来添加同步方法
ChDw 2005-12-22
  • 打赏
  • 举报
回复
你是不能给自己打分的,赫赫
oxmll 2005-12-22
  • 打赏
  • 举报
回复
看来问题基本有个说法了,怎么给分呢?给自己10,给ChDw(米)10?
呵呵,我可是第一次拿分啊。
ChDw 2005-12-22
  • 打赏
  • 举报
回复
这个是当然的,sem1.nofity只可能唤醒sem1.P,这个是PV的最最基本的要求了吧。
因为sem1,sem2已经是两个不同的信号量了。

上面这些当然是JVM已经实现好了,没有看过JVM实现的源代码
oxmll 2005-12-22
  • 打赏
  • 举报
回复
你的意思是:
mySem实例化为sem1和sem2后,sem1的notify,只会唤醒所有使用sem1.P()的进程?
这种机制是怎么实现的,通过this?
没有JAVA的源码,郁闷。
Read the ****ing sources!!!
ChDw 2005-12-22
  • 打赏
  • 举报
回复
你要注意,我说的是同一个对象,而不是同一个类!!!!!!!

sem1和sem2根本不是同一个对象,所以系统不会唤醒thread1


另外一个问题,sem2.V()不可能在thread2中执行的,应该是thread3
醉梦书生 2005-12-22
  • 打赏
  • 举报
回复
学习中,呵呵
oxmll 2005-12-22
  • 打赏
  • 举报
回复
thread1:sem1.P()
thread2:sem2.P()
thread2:sem2.V()

这个时候,不是出问题了吗?如果notify唤醒的是随机的(或者唤醒的是第一个等待的进程),很可能唤醒thread1啊,thread2不是一直就挂起了吗?这时候,thread1实际上应该等待,而不是被唤醒啊!!!

62,629

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧