Java基础-synchronized使用

来源:互联网 发布:最好的网络推广平台 编辑:程序博客网 时间:2024/06/08 15:30

多进程synchronized使用


1.synchronized解释


用于装饰【方法】或【代码块】,保证在同一时刻,多线程环境下,最多只有一个线程可以执行这个方法,当有一个线程执行该代码的时候对,线程进行上锁,执行完毕后释放锁,其他线程开始执行,执行流程类似生产者消费者模式
例子:
1.当有一个线程进入后,对线程计数器 +1
2.其他线程进入时,发现有线程正在执行,线程wait()
3.执行结束后唤醒其他线程,执行notify()方法


2.synchronized使用

//对文件进行读写public class NIOUtils {    public static String read(String filename) throws IOException {        FileInputStream fio = new FileInputStream(filename);        //获取文件通道        FileChannel fc = fio.getChannel();        //分配缓冲区大小        ByteBuffer buffer = ByteBuffer.allocate((int)fc.size());        // 读取文件        fc.read(buffer);        //获取字节数组        byte[] bt=buffer.array();        return new String(bt,0,(int)fc.size());    }    public static void write(String filename, String content) throws IOException {        FileOutputStream fio = new FileOutputStream (filename);        //获取文件通道        FileChannel fc = fio.getChannel();        //分配缓冲区大小        ByteBuffer buffer = Charset.forName("utf8").encode(content);        //buffer.flip();        fc.write(buffer);    }}
//文件内容+1public class AddFileOne implements Runnable {    private String filename = "C:\\download\\test.txt";    @Override    public void run() {            service();    }    private void service(){        try {            Thread.sleep(1000);            String content = NIOUtils.read(filename);            if(content==null||"".equals(content.trim())){                content = "0";            }            Integer count = Integer.valueOf(content);            System.out.println(count);            count++;            NIOUtils.write(filename, count.toString());        } catch (Exception e) {            e.printStackTrace();        }    }}

(1).开启多进程写入文件

public class Main1 {    public static void main(String[] args) {        AddFileOne add = new AddFileOne();        for (int i = 0; i < 100; i++) {            Thread t = new Thread(add);            t.start();        }    }}

结果

010111报错报错

原因是因为多进程写统一文件报出异常

(2).修改代码运行

修改代码如:AddFileOne.java

public void run() {        synchronized (this) {            service();        }    }

或把service方法添加synchronized

private synchronized void service(){

```结果

1
2
3
4
5
6

发现已经成功文件写入成功##3.使用问题###(1).代码块不同步修改Main1.java如下```javapublic class Main1 {    public static void main(String[] args) {        for (int i = 0; i < 100; i++) {            AddFileOne add = new AddFileOne();            Thread t = new Thread(add);            t.start();        }    }}<div class="se-preview-section-delimiter"></div>

运行结果

00011001<div class="se-preview-section-delimiter"></div>

发现代码不同步了

(2).分析原因


这种情况表明,synchronized修饰符,仅仅只对同一个对象开启多线程后,执行某一个方法才进行锁,多个对象的相同方法执行多线时无法进行单线程执行
【java线程锁,只对对象生效,不对代码生效】

(2).解决方法1

修改AddFileOne.java为静态方法

private static synchronized void service(){<div class="se-preview-section-delimiter"></div>

结果

1234<div class="se-preview-section-delimiter"></div>

原因:
因为静态代码在整个工程中属于唯一,内存对象只有一个,同一时间只能一个进程在执行,这么做就是有点浪费资源


如果静态对象不加synchronized,多线程时可以访问的

(3).解决方法2

修改AddFileOne.java,给代码加统一的锁,如下

public class AddFileOne implements Runnable {    String filename = "C:\\download\\test.txt";    private final Object lock;    public AddFileOne(Object lock) {        this.lock = lock;    }    @Override    public void run() {        synchronized (lock){            service();        }    }    private synchronized void service(){        try {            String content = NIOUtils.read(filename);            if(content==null||"".equals(content.trim())){                content = "0";            }            Integer count = Integer.valueOf(content);            System.out.println(count);            count++;            NIOUtils.write(filename, count.toString());        } catch (Exception e) {            e.printStackTrace();        }    }}<div class="se-preview-section-delimiter"></div>

Main1.java运行时传入线程锁

public class Main1 {    public static void main(String[] args) {        Object lock = new Object();        for (int i = 0; i < 100; i++) {            AddFileOne add = new AddFileOne(lock);            Thread t = new Thread(add);            t.start();        }    }}<div class="se-preview-section-delimiter"></div>

结果

12345

4.使用总结

1.synchronized只对对象起作用

2.synchronized static 是对某个类的静态对象方式对线程访问

3.synchronized方法和synchronized代码块一般没有区别,synchronized代码块更能精确访问

4.synchronized不能继承

0 0
原创粉丝点击