博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java核心知识点学习----多线程并发之线程同步
阅读量:7096 次
发布时间:2019-06-28

本文共 4560 字,大约阅读时间需要 15 分钟。

1.什么是线程同步?

 多线程编程是很有趣的事情,它很容易出现"错误情况",这种情况不是由编码造成的,它是由系统的线程调度造成的,当使用多个线程来访问同一个数据时,很容易出现"偶然情况",出现线程安全问题.

线程安全问题最常见的就是银行取钱问题,铁路售票问题,必须保证甲方在操作数据时候,己方不会影响甲方.类似于公共厕所,一个人占一个坑.

2.下面的例子,将说明为什么要保证线程安全?

package com.amos.concurrent;/** * @ClassName: ThreadSynchronizedTest * @Description: 多线程并发之线程同步* @author: amosli* @email:hi_amos@outlook.com* @date Apr 20, 2014 2:44:29 PM  */public class ThreadSynchronizedTest {    public static void main(String[] args) {        new ThreadSynchronizedTest().init();    }        private void init() {        final OutPuter outPuter = new OutPuter();        //新建一个线程A        new Thread(new Runnable() {            public void run() {                while (true) {                    //休息10ms                    try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}                    outPuter.output("hi_amos");//输出                }            }        }).start();        //线程B        new Thread(new Runnable() {            public void run() {                while (true) {                try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}                outPuter.output("amosli");                }            }        }).start();    }    class OutPuter {        //输出name,逐个字节读取,并输出        public void output(String name) {            int length = name.length();            synchronized (name) {                for (int i = 0; i < length; i++) {                    System.out.print(name.charAt(i));                }                System.out.println();            }        }    }}

输出结果如下图所示:

 

在多次执行上面的代码后就会发现出现问题了,这是因为线程A和线程B在执行output方法时,系统调度出现了问题,导致了上面的问题,这种情况出现的概率相对较小,但这种小概率的事件也是要解决的.下面将介绍如何解决这种问题.

3.解决方法1--同步代码块

只需要将上面的方法加上synchronized关键字即可

public void output2(String name) {                int length = name.length();                synchronized (this) {                  for (int i = 0; i < length; i++) {                        System.out.print(name.charAt(i));                    }                    System.out.println();                    }        }

在要多次访问的代码块前加上synchronized关键字,即表示加上排队系统,线程A只有等线程B执行完了才能访问同一个代码块.

这里要注意this,this表示的是当前对象,这里this也可以用Outputer.class代替.

4.解决方法2--同步方法

public synchronized void output(String name) {            int length = name.length();                for (int i = 0; i < length; i++) {                    System.out.print(name.charAt(i));                }                System.out.println();        }

同步方法,即是在要多次访问的方法前面加上synchronized关键字.

注意:

1.synchronized关键字可以修饰方法,代码块,但不能修饰构造器,属性等;

2.同时synchronized关键字最好一个方法中只用一次,否则可能造成死锁.

3.任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定.

 上面的代码可以改写如下:

package com.amos.concurrent;/** * @ClassName: ThreadSynchronizedTest * @Description: 多线程并发之线程安全* @author: amosli* @email:hi_amos@outlook.com* @date Apr 20, 2014 2:44:29 PM  */public class ThreadSynchronizedTest {    public static void main(String[] args) {        new ThreadSynchronizedTest().init();    }        private void init() {        final OutPuter outPuter = new OutPuter();        //新建一个线程        new Thread(new Runnable() {            public void run() {                while (true) {                    //休息10ms                    try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}                    outPuter.output("hi_amos");//输出                }            }        }).start();                new Thread(new Runnable() {            public void run() {                while (true) {                try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}                outPuter.output("amosli");                }            }        }).start();    }    static class OutPuter {        //输出name,逐个字节读取,并输出        public synchronized void output(String name) {            int length = name.length();                for (int i = 0; i < length; i++) {                    System.out.print(name.charAt(i));                }                System.out.println();        }        public void output2(String name) {                int length = name.length();                synchronized (OutPuter.class) {                    for (int i = 0; i < length; i++) {                        System.out.print(name.charAt(i));                    }                    System.out.println();                    }        }        public synchronized static void output3(String name) {            int length = name.length();                for (int i = 0; i < length; i++) {                    System.out.print(name.charAt(i));                }                System.out.println();            }    }}
View Code

 

 

 

 

 

 

转载地址:http://cyhql.baihongyu.com/

你可能感兴趣的文章
程序后台服务启动,MongoDB未启动(启动较慢)/(关机重启情况下)。
查看>>
数据库系统阶段特点
查看>>
假期演练1-3
查看>>
梦断代码读后感
查看>>
jdbc的配置及jdbc连接常用数据库(mysql、sqlserver、Oracle)
查看>>
java获取程序执行时间
查看>>
eclipse连hadoop2.x运行wordcount 转载
查看>>
HTML5:Details元素
查看>>
WEB前端底层知识之浏览器是如何工作的(2)--渲染引擎 BY: linFen
查看>>
ActionBar的简单应用
查看>>
IE11下不能引入外部css的解决方法
查看>>
java web 答辩总结
查看>>
GUI测试含义
查看>>
javabean使用技巧
查看>>
JS/JQ综合总结
查看>>
CGAffineTransform相关函数
查看>>
字符编码与字符集区别与联系(网页/PHP文件/MYSQL数据库乱码问题)
查看>>
黑马程序员-----const和readonly的区别
查看>>
转载:基于MapXtreme的鹰眼功能
查看>>
黄聪:远程序桌面登录的.NET(C#)开发
查看>>