线程的安全问题
当一个线程在执行操作共享数据的多条代码的过程中,其它线程参与运算,就会导致线程问题的产生
解决思路:
将多条操作共享数据的线程代码封装起来,当线程在执行这些代码的时候,
其他线程不可以参与运算.
必须要当前把这些代码执行完毕后,其它线程才可以参与运算.
同步代码
同步代码块的格式:
synchronized(对象)
{
需要被同步的代码;
}
例子:
class Ticket implements Runnable //Ticket票
{
private int num = 100;
Object obj = new Object();
public void run()
{
while(true)
{
//同步代码块
synchronized(obj)
{
if (num > 0)
{
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{}
System.out.println(Thread.currentThread().getName() + "......总票数剩余" + num--);
}
}
}
}
}
public class Demo{
public static void main(String[] args){
Ticket t = new Ticket(); //创建一个线程任务对象
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行多次的结果:
(1)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSP9cWTzsmeOBzaq1EM4wmYwhGWhxGZzwEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3PnBnaukzNwETNzMjM2IDMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
(2)
同步的好处:解决了线程的安全问题
同步的弊端: 相对降低了效率....因为同步外的线程都会判断同步锁
(因为如果有线程在同步里面,刚好CPU又突然给别的线程权限,但又进不去)
(等到CPU重新给到在同步代码块里面的执行完毕出来后,才能给别的线程进去,所以降低了效率.)
同步的前提: 同步中必须有多线程并使用同一个锁
.
.
.
.
同步函数
就是把同步代码块封装起来
例子:
public synchronized void show(){ //把同步代码块封装起来
if (num > 0) {
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + "...function...总票数剩余" + num--);
}
这里面的锁是对象是 this 也就是 它本身
也就说在上面的例子中我们可以不用Object 创建一个对象来当锁,而可以用自己的锁 this
可以写成这样
synchronized (this) {
if (num > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName() + "....总票数剩余" + num--);
}
同步函数使用的锁是this
同步函数和同步代码块的区别:
同步函数的锁是固定的this.
同步代码块的锁是任意的对象
建议使用同步代码块
因为同步函数虽然简化,但是锁是唯一的…this
.
.
.
.
.
静态的同步函数
静态的同步函数使用的锁:
该函数所属字节码对象 可以用 getClass()方法获取
也可以用当前 类名.class 表示
例子:
可以
this.getClass()
//this当前的
Ticket是上面的类名 也可以
Ticket.class
synchronized(Ticket.class)
{
if (num > 0)
{
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{}
System.out.println(Thread.currentThread().getName() + "......总票数剩余" + num--);
}
一般只要保证多个线程用同一个锁就行!!!