`
Alex__Liu
  • 浏览: 2808 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

类中同步方法被调用,其他方法是否可以同时被调用

阅读更多
    毕业初期,面试时经常被问到一个问题:一个类中同步方法被调用时,它的其他方法是否可以同时被调用?记得当时看过面试宝典,答案是否,不能被调用。但是其实这个答案是错误的。
正确的回答应该是该类中其他同步方法不能被同时调用,但非同步方法可以被调用。下面给出例子。
Business.java
package thread;

public class Business
{
    
    public synchronized void methodA() throws InterruptedException
    {
        Thread.sleep(10000);
        System.out.println("I am method A, I am a synchronized method");
    }
    
    public void methodB()
    {
        System.out.println("I am not a synchronized method, check if i can be called when the a synchronized method are called");
    }
    
    public synchronized void methodC()
    {
        System.out.println("I am a synchronized method, check if i can be called when the a synchronized method are called");
    }
}



Thread1.java
package thread;

public class Thread1 implements Runnable
{
    private Business bus;
    public Thread1(Business b)
    {
        this.bus = b;
    }
    @Override
    public void run()
    {
        try
        {
            bus.methodA();
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}



Thread2.java
package thread;

public class Thread2 implements Runnable
{
    private Business bus;
    public Thread2(Business b)
    {
        this.bus = b;
    }
    @Override
    public void run()
    {
        bus.methodB();
    }

}



thread3.java
package thread;

public class Thread3 implements Runnable
{
    private Business bus;
    public Thread3(Business b)
    {
        this.bus = b;
    }
    @Override
    public void run()
    {
        bus.methodC();
    }

}



TestMain.java
package thread;

public class TestMain
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        Business b = new Business();
        Thread th1 = new Thread(new Thread1(b));
        Thread th2 = new Thread(new Thread2(b));
        Thread th3 = new Thread(new Thread3(b));
        th1.start();
        th2.start();
        th3.start();
    }

}



运行会发现methodB的会立即被执行,但是methodA会sleep 10s,然后跟着methodC执行。

其实很容易理解,用sychronized把methodA和methodC加锁,默认情况下sychronized是对当前class类对象加锁,相当于
    public void methodA() throws InterruptedException
    {
        synchronized(this)
        {
            Thread.sleep(10000);
            System.out.println("I am method A, I am a synchronized method");
        }
       
    }

 public void methodC()
    {
        synchronized(this)
        {
            System.out.println("I am a synchronized method, check if i can be called when the a synchronized method are called");
        }
        
    }


所以当methodA持有锁时methodC就不能拿到锁,故不能被调用,而methodB则不需要获取锁,故可以被执行
1
2
分享到:
评论
4 楼 Alex__Liu 2013-06-04  
picasso.di 写道
感觉您关于同步方法的论述有一些问题,我的理解是,实例方法中加入sychronized关键字封锁的是this对象本身,而在静态方法中加入sychronized关键字封锁的就是类本身,您给的例子里,方法都是实例方法,所以sychronized是对this加锁,而不是对class加锁,如果您给的方法是static的,那么就是对class加锁了。如果我有说的不对的地方,请指正!

你是对的,我疏忽了,已更正,谢谢
3 楼 picasso.di 2013-06-04  
感觉您关于同步方法的论述有一些问题,我的理解是,实例方法中加入sychronized关键字封锁的是this对象本身,而在静态方法中加入sychronized关键字封锁的就是类本身,您给的例子里,方法都是实例方法,所以sychronized是对this加锁,而不是对class加锁,如果您给的方法是static的,那么就是对class加锁了。如果我有说的不对的地方,请指正!
2 楼 ifoggy 2013-06-04  
其实明白synchronized关键字的作用就比较容易理解了,synchronized默认是会所住类对象的内部锁,而非synchronized方法并不会加上这个锁,自然可以被额外的线程调用执行。
1 楼 teasp 2013-06-04  
面试宝典上的错误一堆一堆的的。

相关推荐

    Java异步调用转同步方法实例详解

    Java异步调用转同步方法实例详解 Java异步调用转同步方法实例详解是指在Java中将异步调用转换为同步调用的...Java中有多种方法将异步调用转换为同步调用,开发者可以根据实际情况选择合适的方法来实现异步调用转同步。

    C#调用C++类中的方法

    通过以上步骤,你可以在C#项目中成功调用C++类中的方法。记住,确保正确配置DLL的路径、调用约定和封送规则,这是成功调用的关键。虽然网上资源相对较少,但只要理解了这些基本原理,就可以自己解决类似问题。

    Java 线程同步调用

    在深入探讨Java线程同步调用这一主题之前,我们首先需要理解线程同步的基本概念及其在多线程环境中的重要性。线程同步是多线程编程中的一个关键概念,它确保了多个线程在访问共享资源时不会发生冲突,避免了数据不...

    js调用C#方法

    在C#代码中可以通过`Request.Params`获取传递过来的参数: ```csharp protected void Page_Load(object sender, EventArgs e) { string target = Request.Params["__EVENTTARGET"]; string args = Request.Params...

    C#调用C++DLL导出类

    由于C#不支持直接调用C++类,我们需要将C++类的方法转换为C风格的函数接口,因为C#可以直接调用这些接口。 ```csharp // 使用DllImport加载DLL [DllImport("MyCppDll.dll", CallingConvention = CallingConvention....

    Angular异步变同步处理方法

    这些操作的结果通过deferred对象.promise返回,之后可以链式调用then方法,then方法中可以定义成功回调、失败回调和状态变更回调。 在前端开发中,经常遇到的一个场景是多个接口的调用顺序依赖问题。例如,页面需要...

    Nodejs让异步变成同步的方法

    Node.js中让异步操作变成同步的方法通常是指将非阻塞的异步调用改写为在逻辑上表现得像同步调用的方式。Node.js中异步操作是通过回调函数、Promises和async/await等技术来实现的。以下我们详细讲解如何通过这些方法...

    Spring Boot中Controller间的调用

    本文将探讨两种在Spring Boot中实现Controller间调用的方法及其优缺点。 首先,我们可以使用`RestTemplate`来模拟远程调用。这是一种常见的HTTP客户端工具,允许Controller A通过HTTP请求访问Controller B。以下是...

    cefsharp JavaScript调用C#方法并返回参数

    2. 调用C#方法:在JavaScript中,可以使用`window.chrome.webview`对象的`call`方法来调用C#方法。假设我们有一个名为`addNumbers`的C#方法,接受两个整数参数并返回它们的和,JavaScript代码可能如下: ```...

    JAVA方法调用万年历

    在Java编程中,"JAVA方法调用万年历"是一个常见的练习项目,它涉及到日期和时间处理、控制台输出以及方法的组织与调用。在这个项目中,开发者通常会创建一个程序,能够显示从公元1到公元9999年的所有日期,即...

    WCF 同步 异步调用 实例

    在WCF中,同步调用通过调用服务接口的方法直接完成。以下是一段简单的同步调用示例: ```csharp using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client()) { string result = ...

    C#同步调用,异步调用,异步回调.docx

    在 C# 编程中,调用方法可以分为同步调用和异步调用两种。同步调用是指当前线程阻塞,等待方法执行完毕后继续执行,而异步调用则是将方法调用交给线程池,当前线程继续执行不阻塞。异步调用可以使用 BeginInvoke 和 ...

    如何在WPF应用程序中通过HttpClient调用Web API

    在WPF应用程序中,异步调用Web API是一项重要的技术,因为它可以避免UI线程阻塞,从而提高用户体验。在.NET框架中,HttpClient类提供了异步调用Web API的能力。本文将详细介绍如何在WPF应用程序中使用HttpClient异步...

    方法调用序列追踪工具

    - **调用频率**:统计了每个方法被调用的次数,对性能瓶颈分析有帮助。 - **调用路径**:追踪了特定方法的调用路径,有助于定位问题根源。 - **并发行为**:在多线程环境下,可以揭示方法之间的同步和互斥关系。 ...

    静态方法同步 与 非静态方法同步

    每个对象都有自己的锁,因此不同的实例可以同时执行各自的同步方法,而不会相互干扰。这种同步方式适用于保护对象内部的状态,防止不同实例之间的数据冲突。 例如,`SynchronizedTest.java`中可能有以下非静态同步...

    在C或C++中调用JAVA方法

    在JNI编程中,首先要有一个Java类,该类包含将被C/C++调用的方法。例如,我们可以创建一个名为`Demo`的Java类,包含静态和非静态方法,属性,数组,以及异常处理。以下是一个简单的`Demo`类示例: ```java package ...

    android服务的开启方式及调用服务中的方法的实现

    绑定服务允许客户端和服务之间建立持久连接,这样就可以直接调用服务中的接口方法。以下是一般步骤: 1. **定义服务接口**:在服务类中创建一个接口,声明需要调用的方法。 ```java public interface Service...

    线程及方法调用

    在这个例子中,`isStop`标志用于控制线程的停止,当`stop()`方法被调用时,`isStop`变为`true`,`run()`方法的循环会因条件不满足而结束,从而终止线程。 线程的并发执行能够提高程序的效率,但同时也引入了线程...

    NDK开发之C语言调用Java构造方法、父类方法、返回中文字符串乱码问题案例

    在Android开发中,NDK(Native ...总之,NDK开发中的C/C++调用Java方法是一项关键技能,它能让你充分利用原生代码的优势,同时解决Java层难以处理的问题。理解和熟练运用JNI,将使你的Android应用性能更上一层楼。

Global site tag (gtag.js) - Google Analytics