线程-关于java sychronized锁代码块对该对象的其它sychonized方法是否有影响的问题。

问题描述

关于java sychronized锁代码块对该对象的其它sychonized方法是否有影响的问题。

代码是书上例子,我简化了,启用线程ob1后,通过主线程调用sychonized方法mysuspend()和myresume()来控制ob1线程的等待与重启。线程从15开始倒数,0.5秒个,主线程在1秒时候暂停文字提示,再过1秒重启线程。例子中的sychonized代码块仅包含wait()判定部分,输出与预期一样,倒数到14的时候中断,之后又恢复。但是当我将sychonized代码块前移,包含至 Thread.sleep(500)之前的时候,暂停时间常常之后到13时候,当sychonized代码块前移包含整个循环语句的时候,倒数代码段根本就停不下来,结束的时候主线程才调用了下mysuspend()挂起方法,就好像整个
ob1对象被锁住似的,所以请问,sychonized代码块锁住的地方和mysuspend()挂起方法是分别加锁,双方互相独立ob1可以同时进行两个部分,为什么后两种情况明显感到ob1.mysuspend()被锁住动不了的呢?

public class NewThread implements Runnable{

String name;
Thread t;
static boolean suspendFlag;

NewThread(String threadname)
{
    name=threadname;
    t=new Thread(this,name);
    System.out.println("New thread:"+t);
    suspendFlag=false;
    t.start();
}

public void run()
{

    try
    {
        for(int i=15;i>0;i--)
    {

            System.out.println(name+":"+i);

    Thread.sleep(500);
    synchronized(this){while(suspendFlag){this.wait();}}
    }
    }

    }catch(InterruptedException e){}

    System.out.println(name+" exiting.");

    }

synchronized  void mysuspend(){suspendFlag=true;}
synchronized  void myresume(){suspendFlag=false;notify();}

}

public static void main(String[] args) {

NewThread ob1=new NewThread("One");
NewThread ob2=new NewThread("Two");
try{
Thread.sleep(1000);

ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);

ob1.myresume();
System.out.println("Resuming thread One");

}catch(InterruptedException e){}

解决方案

sychonized方法是不会影响其它的sychonized方法,一人sychonized上锁了,另一个sychonized方法只要没上锁就可以访问

解决方案二:

synchronized的参数就是监视器对象,只要监视器对象不同(即锁住的对象不同),即使是同一个对象的不同synchronized代码块之间是没有影响的。
你的代码中线程的run方法中使用到的是synchronized(this)就是当前线程对象,而静态方法的synchronized上的监视器对象是整个类的class类型信息,是不同的监视器对象,所以不会相互影响的。
运行了你的代码,你的run方法中使用的synchronized(this)是当前对象,而while(suspendFlag)条件变量又是静态全局的,所以当你将线程one先挂起后该标识为true,此时线程two执行到这行语句后的this.wait()就会将自己挂起,然后main函数正常resume了线程one,并且唤醒了自己。但是线程two没有被唤醒。所以最后的结果是线程one正常退出,而线程two就被挂起了,这个程序一直处于无法结束的状态。

Object的wait和notify是条件队列,只能唤醒和挂起在当前对象this上的线程,你的两个线程one和two在执行run方法时都有各自的this对象,都是在各自的this锁上的wait和notify,线程one正常退出是因为先wait后又notify,而线程two只wait挂起了,没有人来唤醒它就永远挂起了。

解决方案三:

补充一点:如果要让线程two正常结束则需要调用resume唤醒该线程,在最后执行一次ob2.myresume();它会将flag为false并且notify唤醒自己,程序就能正常结束了。

时间: 2024-08-30 09:17:32

线程-关于java sychronized锁代码块对该对象的其它sychonized方法是否有影响的问题。的相关文章

java中static{.......}代码块的作用

问题描述 java中static{.......}代码块的作用 java中static{.......}代码块主要用在哪里,表示什么意思,有什么用,里面主要写什么内容 解决方案 static后不跟方法名,这个块在该类第一次加载的时候运行,就是说比初始化模块还早就运行,一般用于加载该类需要一次性完成的功能使用. 解决方案二: Java中的static静态代码块 解决方案三: 初始化用,不需要创建实例,当你访问这个类时,就会执行 解决方案四: static 就是静态.你可以搜索一下关于静态的解释.网

Java 构造函数 静态代码块

问题描述 Java 构造函数 静态代码块 public class 静态 { public static void main(String[] args) { person p=new person(); p.show(); person p1=new person("xixi"); p1.show(); } } class person{ ** 这里显示"person"错误** private String name; { cry(); } { System.ou

线程安全-存储过程怎么让代码块同步执行

问题描述 存储过程怎么让代码块同步执行 问题是这样的:一个表,传入参数(多个) 判断 如果表中有这个数据(有一个或者多个参数标识这条记录唯一),更新这条数据 如果表中不存在这条数据,新增一条. 现在把这个逻辑写到存储过程中了,会出现多个线程同时调用这个存储过程,在查询.没插入之前,有多个线程得到都是数据库没有记录的,导致插入多条数据. 怎么把这个过程变成原子的,锁定这块代码. 锁表不太科学,锁行,因为插入之前,数据是不存在的,也锁不住,求帮忙,非常感谢! 这个问题应该不是事务吧?事务是代码可能执

深入浅析Java中普通代码块、构造代码块与静态代码块_java

//执行顺序:(优先级从高到低.) 静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1.普通代码块 public static void main(String[] args) { /*普通代码块: *直接定义在在方法或语句中出现"{普通代码的执行语句}"的就称为普通代码块. *普通代码块执行顺序由他们在代码中出现的次序决定--"先出现先执行" * */ { System.out.p

Java面向对象基础--代码块

1.普通代码块 public class CodeDemo01{ public static void main(String args[]){ { // 普通代码块 int x = 30 ; // 就属于一个局部变量 System.out.println("普通代码块 --> x = " + x) ; } //int x = 100 ; // 与局部变量名称相同 System.out.println("代码块之外 --> x = " + x) ; }

基本线程同步(五)使用Lock同步代码块

声明:本文是< Java 7 Concurrency Cookbook >的第二章,作者: Javier Fernández González     译者:许巧辉 校对:方腾飞 使用Lock同步代码块 Java提供另外的机制用来同步代码块.它比synchronized关键字更加强大.灵活.它是基于Lock接口和实现它的类(如ReentrantLock).这种机制有如下优势: 它允许以一种更灵活的方式来构建synchronized块.使用synchronized关键字,你必须以结构化方式得到释

Java多线程-线程的同步与锁的问题_java

一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. package cn.thread; public class Foo { private int x = 100; public int getX() { return x; } public int fix(int y) { x = x - y; return x; } } package cn.thread

Java 25天基础-DAY 06-面向对象-静态代码块

/* 静态代码快 格式: static { 静态代码块中的执行语句. } 特点:随着类的加载而执行,只执行一次.优先于主函数执行. 用于给类进行初始化 / / class StaticCode { static { System.out.println("a"); } } */ class StaticCodeDemo { static { System.out.println("b"); } public static void main(String[] arg

Ruby的代码块、迭代子和过程对象

在Ruby的一切都是一个对象.甚至一个代码块也是一个对象!在Ruby中,代码对象被称为代码块.你可以把代码块想像成小的程序单元.它们包含Ruby代码并且能够在执行它们时转入到方法中.在Python,C和Java中与之类似的概念是函数指针,匿名函数,内部类和回调函数. Ruby代码块的语法是,把Ruby代码放在大括号之间或放在do/end命令之间.如下所示: { #这是一个代码块... } do #...并且这也是一个代码块 end 在一个很简单的实例中,{puts"hello world&quo