类锁和对象锁的简单区别

1.用static 修饰的方法再加上sychonized 相当于是一个类锁,类名加方法名就能访问这个方法

    对象锁,是指只有那个对象加上方法名才能访问的

2.同步通信和异步通信的区别

  同步:我叫你吃饭,你若暂时有事情我就一直在那等,不干别的事情,直到你忙完。
    异步:我叫你吃饭,你若暂时有事情,我就先撤,干点别的,你忙完了再通过某种方式,如电话,通知我。
这两者没有什么好不好之分,适用场景决定方式,简单举例来首,如果是IO密集型的,可能会用同步IO,否则可能会用异步IO。



A B 方法是加了类锁

C D 方法是对象锁

package Test02;

import java.util.Date;

/**
 * create by Sun
 * 2018/6/25
 */
public class Task2 {
    /**
     * 类锁
     */
    public  synchronized static void  doLongTimeTaskA(){
        System.out.println("name = " + Thread.currentThread().getName() +", begain"+", time="+System.currentTimeMillis());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("name = " + Thread.currentThread().getName() + ", end"+", time="+System.currentTimeMillis());
    }

    /**
     * static (static方法可以直接使用类调用)类锁,类锁是同步的(同步通信,及时一个线程执行,另一个线程必须等待)
     *
     */
    public  synchronized static void  doLongTimeTaskB(){
        System.out.println("name = " + Thread.currentThread().getName() + ", begain"+", time="+System.currentTimeMillis());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("name = " + Thread.currentThread().getName() + ", end"+", time="+System.currentTimeMillis());
    }

    /**
     * 对象锁(是异步的,即一个线程执行了,开启另一个线程接收,指的是不同类型的锁的实现)
     * 如果两种锁都是同一种类型的,那么他们指向的顺序还是要进行堵塞,竞争,一个个的执行
     * (这种只能是对象调用,对象锁)
     */
    public  synchronized void doLongTimeTaskC(){
        System.out.println("name = " + Thread.currentThread().getName() + ", begain"+", time="+System.currentTimeMillis());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("name = " + Thread.currentThread().getName() + ", end"+", time="+System.currentTimeMillis());
    }
    public  synchronized void doLongTimeTaskD(){
        System.out.println("name = " + Thread.currentThread().getName() + ", begain"+", time="+System.currentTimeMillis());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("name = " + Thread.currentThread().getName() + ", end"+", time="+System.currentTimeMillis());
    }
}

2.下面四个线程进行,测试

package Test02;

/**
 * create by Sun
 * 2018/6/25
 */
public class ThreadA extends Thread {
    private Task2 mTask2;

    public ThreadA(Task2 tk){
        mTask2 = tk;
    }

    @Override
    public void run() {
        /**
         * 测试不同的锁之间的变化  Test1
         */
       //1. mTask2.doLongTimeTaskA();
        /**
         * 测试不同对象的对象锁的变化 Test2
         */
        //2  mTask2.doLongTimeTaskC();
        /**
         * 测试类锁对不同对象的对象锁的变化 Test3
         */
        mTask2.doLongTimeTaskA();
    }
}

package Test02;

/**
 * create by Sun
 * 2018/6/26
 */
public class ThreadB extends Thread {
    private Task2 mTask2;

    public ThreadB(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        /**
         * 测试不同的锁之间的变化
         */
         //1. mTask2.doLongTimeTaskB();
        /**
         * 测试不同对象的对象锁的变化
         */
        mTask2.doLongTimeTaskA();
    }
}



package Test02;

/**
 * create by Sun
 * 2018/6/26
 */
public class ThreadC extends Thread {
    private Task2 mTask2;

    public ThreadC(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        mTask2.doLongTimeTaskC();
    }
}

package Test02;

/**
 * create by Sun
 * 2018/6/26
 */
public class ThreadD extends Thread {
    private Task2 mTask2;

    public ThreadD(Task2 tk){
        mTask2 = tk;
    }

    public void run() {
        mTask2.doLongTimeTaskD();
    }
}

package Test02;

/**
 * create by Sun
 * 2018/6/25
 */
public class main02 {
    public static void main(String[] args) {
       // new main02().Test1();
       // new main02().Test2();
        new main02().Test3();

    }
    public void Test1(){
        Task2 task2=new Task2();
        ThreadA ta=new ThreadA(task2);
        ThreadB tb=new ThreadB(task2);
        ThreadC tc=new ThreadC(task2);
        ThreadD td=new ThreadD(task2);

        ta.setName("A");
        tb.setName("B");
        tc.setName("C");
        td.setName("D");

        ta.start();
        tb.start();
        tc.start();
        //  tb.start();
        td.start();

        System.out.println("name = A, begain, time=1529977090289\n" +
                "name = C, begain, time=1529977090289\n" +
                "name = C, end, time=1529977091290\n" +
                "name = D, begain, time=1529977091290\n" +
                "name = A, end, time=1529977091291\n" +
                "name = B, begain, time=1529977091291\n" +
                "name = D, end, time=1529977092291\n" +
                "name = B, end, time=1529977092292");
        System.out.println("1.------总结----------对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的");

    }
    public void Test2(){
        Task2 task2a=new Task2();
        Task2 task2b=new Task2();
        ThreadA ta=new ThreadA(task2a);
        ThreadB tb=new ThreadB(task2b);

        ta.setName("A");
        tb.setName("B");
        ta.start();
        tb.start();

        System.out.println("----不同对象的对于对象锁的执行的顺序-------异步执行");
        System.out.println("运行结果\n"+"name = A, begain, time=1529977658292\n" +
                "name = B, begain, time=1529977658292\n" +
                "name = B, end, time=1529977659293\n" +
                "name = A, end, time=1529977659293");
    }
    public void Test3(){
        Task2 task2a=new Task2();
        Task2 task2b=new Task2();
        ThreadA ta=new ThreadA(task2a);
        ThreadB tb=new ThreadB(task2b);

        ta.setName("A");
        tb.setName("B");
        ta.start();
        tb.start();

        System.out.println("----类锁的对于对象锁的执行的顺序-------同步执行");
        System.out.println("执行结果\n"+"name = A, begain, time=1529989536919\n" +
                "name = A, end, time=1529989537920\n" +
                "name = B, begain, time=1529989537920\n" +
                "name = B, end, time=1529989538922");
    }
}


<think>我们被要求提供Android中简单对象锁的使用示例代码。根据引用内容,我们可以总结如下: 1. **对象锁**:定的是当前对象实例,不同对象实例之间互不影响。 2. ****:实际上是的Class对象,因此对的所有实例都起作用。 下面我们分别给出示例代码。 ### 一、对象锁示例 对象锁有两种形式: - 修饰实例方法:是当前对象实例(this) - 同步代码块:指定一个对象作为(通常使用this或一个专门的对象) #### 1.1 修饰实例方法 ```java public class Example { // 对象锁:修饰实例方法,是当前对象实例(this) public synchronized void objectLockMethod() { // 临界区代码 System.out.println("对象锁方法执行中..."); } } ``` #### 1.2 同步代码块(使用this) ```java public class Example { public void objectLockBlock() { // 非同步代码... // 使用this作为 synchronized (this) { // 临界区代码 System.out.println("对象锁代码块执行中..."); } // 其他非同步代码... } } ``` #### 1.3 同步代码块(使用专用对象) ```java public class Example { // 专用对象,推荐使用final修饰 private final Object lock = new Object(); public void objectLockWithCustomLock() { // 非同步代码... synchronized (lock) { // 临界区代码 System.out.println("使用专用对象的代码块执行中..."); } // 其他非同步代码... } } ``` ### 二、示例 也有两种形式: - 修饰静态方法:是当前的Class对象(如Example.class) - 同步代码块:指定的Class对象作为 #### 2.1 修饰静态方法 ```java public class Example { // :修饰静态方法,是当前的Class对象 public static synchronized void classLockMethod() { // 临界区代码 System.out.println("方法执行中..."); } } ``` #### 2.2 同步代码块(使用Class对象) ```java public class Example { public void classLockBlock() { // 非同步代码... // 使用的Class对象作为 synchronized (Example.class) { // 临界区代码 System.out.println("代码块执行中..."); } // 其他非同步代码... } } ``` ### 三、对象锁区别验证 为了说明对象锁区别,我们可以通过以下场景验证: 1. **对象锁**:同一个对象实例的不同同步方法(或代码块)会互斥,但不同对象实例之间不会互斥。 2. ****:所有对象实例的方法(或代码块)都会互斥。 #### 验证代码: ```java public class LockTest { public static void main(String[] args) { // 创建两个不同的实例 Example example1 = new Example(); Example example2 = new Example(); // 线程1:使用example1调用对象锁方法 new Thread(() -> { example1.objectLockMethod(); }).start(); // 线程2:使用example2调用对象锁方法(不会阻塞,因为不同对象) new Thread(() -> { example2.objectLockMethod(); }).start(); // 线程3:使用example1调用方法 new Thread(() -> { Example.classLockMethod(); }).start(); // 线程4:使用example2调用方法(会阻塞,直到释放) new Thread(() -> { Example.classLockMethod(); }).start(); } } ``` ### 四、注意事项 1. **避免字符串**:如`synchronized("LOCK")`,因为字符串常量池可能导致多个地方意外共享同一个。 2. **对象的选择**:推荐使用专用的私有对象(private final),这样可以避免外部意外获取导致死。 3. **的作用范围**:会影响该的所有实例,因此在高并发场景下需谨慎使用,避免性能瓶颈。 ### 五、总结 - **对象锁**:作用于对象实例,不同实例之间不互斥。 - ****:作用于的Class对象,所有实例共享同一把。 通过以上示例代码验证,我们可以清晰地理解两种的使用方式区别。 --- §§相关问题§§ 1. 如何在Android中正确使用`wait()``notify()`实现线程间通信? 2. 对象锁在性能上有何差异? 3. 如何避免在Android中使用时出现死? 4. `ReentrantLock`与`synchronized`在对象锁场景下的替代方案?</think>### Android 对象锁使用示例 #### 一、对象锁(实例级定当前对象实例,不同对象实例之间互不影响: ```java public class OrderProcessor { // 专用对象(推荐) private final Object lock = new Object(); // 方式1:同步代码块(显式指定对象) public void processOrder(String orderId) { // 非同步操作... synchronized(lock) { // 定当前对象实例 [^1] System.out.println("处理订单: " + orderId); // 临界区代码 } } // 方式2:synchronized方法(隐式使用this作为) public synchronized void updateInventory() { // 等价于synchronized(this) System.out.println("更新库存"); // 临界区代码 } } ``` **使用场景**: ```java OrderProcessor processor1 = new OrderProcessor(); OrderProcessor processor2 = new OrderProcessor(); // 不同对象不会互相阻塞 new Thread(() -> processor1.processOrder("A123")).start(); new Thread(() -> processor2.processOrder("B456")).start(); // 可并行执行 ``` #### 二、(全局的Class对象,所有实例共享同一把: ```java public class PaymentService { // 方式1:静态同步方法 public static synchronized void processPayment() { // PaymentService.class [^2] System.out.println("处理支付"); // 临界区代码 } // 方式2:同步代码块使用Class对象 public void logTransaction() { // 非同步操作... synchronized(PaymentService.class) { // 显式 System.out.println("记录交易日志"); // 临界区代码 } } } ``` **使用场景**: ```java PaymentService service1 = new PaymentService(); PaymentService service2 = new PaymentService(); // 不同实例访问方法会互斥 new Thread(() -> service1.processPayment()).start(); new Thread(() -> service2.processPayment()).start(); // 会阻塞等待 ``` #### 三、对象锁 vs 对比 | 特性 | 对象锁 | | |--------------|----------------------------------|-----------------------------------| | **对象** | 当前实例(this) | 的Class对象 | | **作用范围** | 仅限当前对象实例 | 所有对象实例共享 | | **适用场景** | 对象内部状态保护 | 全局资源/静态数据保护 | | **并发性** | 不同实例可并行操作 | 所有实例互斥访问 | | **实现方式** | `synchronized(this)`或实例方法 | `synchronized(ClassName.class)` | #### 四、高级用法:wait()/notify() 配合对象锁实现线程协作: ```java public class TaskQueue { private final Queue<String> queue = new LinkedList<>(); private final Object lock = new Object(); // 专用对象 [^4] public void addTask(String task) { synchronized(lock) { queue.add(task); lock.notify(); // 唤醒等待线程 } } public String getTask() throws InterruptedException { synchronized(lock) { while(queue.isEmpty()) { lock.wait(); // 释放并等待 } return queue.poll(); } } } ``` > **关键实践**: > 1. 优先使用私有对象(`private final Object lock`)而非`synchronized(this)`,避免外部代码意外获取 > 2. 慎用于高频操作,可能成为性能瓶颈 > 3. 同步块尽量缩小范围,减少持有时间 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值