Java多线程(二) synchronized 针对对象进行锁定

会有一股神秘感。 提交于 2020-03-28 06:59:57

http://www.cnblogs.com/QQParadise/articles/5059824.html

 

1.方法内的变量为线程安全的

2.实例变量非线程安全的

public class HasSelfPrivateNum {
    
    private int num = 0;
    synchronized public void addI(String username) {
        try {
            
            if (username.equals("a")) {
                System.out.println("a set over");
                num = 100;
                Thread.sleep(2000);
            }else{
                num =200;
                System.out.println("b set over");
            }
            System.out.println(username+" num="+num);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

ThreadA

public class ThreadA extends Thread{

    private HasSelfPrivateNum numRef;
    
    public ThreadA(HasSelfPrivateNum numRef){
        this.numRef =numRef;
    }
    
    public void run(){
        numRef.addI("a");
    }
}
View Code

ThreadB

public class ThreadB extends Thread{

    private HasSelfPrivateNum numRef;
    
    public ThreadB(HasSelfPrivateNum numRef){
        this.numRef =numRef;
    }
    
    public void run(){
        numRef.addI("b");
    }
}
View Code

Run

public class RunDemo {

    public static void main(String[] args) {
        
        HasSelfPrivateNum numRef = new HasSelfPrivateNum();
        
        HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();
        ThreadA athread = new ThreadA(numRef);
        athread.start();

        ThreadB bthread = new ThreadB(numRef2);
        bthread.start();

    }
}

例子不会发生脏读,因为是不同的对象

非线程安全其实会在多线程对同一个对象中的实例变量进行并发访问时发生,
产生的后果就是“脏读”,也就是取到的数据其实是被更改过的。

1)调用关键字synchronized声明的方法一定是排队运行的。只有共享资源的读写访问才需要同步化,如果不是共享资源,那么根本就没有同步的必要。
2)synchronized 同步块
不在synchronized块中就是异步执行,在synchronized块中就是同步执行
3)多个线程调用一个对象中的不同名称的synchronized同步方法或synchronized(this) 同步代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的。
4) 锁非this 对象具有一定的优点:如果在一个类中有很多个synchronized方法,这时
虽然能实现同步,但会受到阻塞,所以影响运行效率;但如果使用同步代码块锁非
this对象,则synchronized(this) 代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁,则可以大大提高运行效率。
4.volatile 强制性从公共堆栈中进行取值,增加了实例变量在多个线程之间的可见性

public class Run {

    public static void main(String[] args) throws InterruptedException {
        Task task = new Task();
        ThreadA threadA = new ThreadA(task);
        threadA.setName("A");
        threadA.start();
        Thread.sleep(100);
        ThreadB threadB = new ThreadB(task);
        threadB.setName("B");
        threadB.start();    
    }
}
public class Task {

    synchronized public void otherMethod() {
        System.out.println("-----------run othermethod");
    }

    synchronized public void doLongTimeTask() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("syn threadName=" + Thread.currentThread().getName() + "i=" + (i + 1));
            }
    }
}

 

public class ThreadA extends Thread {

    private Task task;
    
    public ThreadA(Task task){
        this.task =task; 
    }
    public void run(){
        task.doLongTimeTask();
    }
}

public class ThreadB extends Thread {

    private Task task;
    
    public ThreadB(Task task){
        this.task =task; 
    }
    public void run(){
        task.otherMethod();
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!