在java程序中,若是有多个线程同时运行,而且同时执行同一段代码,若是程序每次运行的结果和单线程运行的结果是同样的,并且其余变量的值也和预期是同样的,那么这段代码就是线程安全的。java
可是在多线程操做中也可能会有一些线程安全的问题发生。web
以卖票事例做为说明,有100张票往外售卖,售完结束。安全
public class Tickets implements Runnable{
//初始化票数
private int ticket=100;
public void run() {
//卖票
while (true){
if(ticket>0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
}
}
}
}
public class TicketsTest {
public static void main(String[] args) {
//声明变量
Tickets tickets = new Tickets();
//建立三个线程(窗口)
Thread t1 = new Thread(tickets,"窗口1");
Thread t2 = new Thread(tickets,"窗口2");
Thread t3 = new Thread(tickets,"窗口3");
//三个窗口同时买票
t1.start();
t2.start();
t3.start();
}
}
可是在运行结果中会发生如下这种状况:票已经卖出,可是总数没有减小;或者票已经售空,仍然在减票的状况多线程
窗口3正在卖:100
窗口1正在卖:99
窗口2正在卖:100
窗口1正在卖:98
.......
窗口2正在卖:4
窗口1正在卖:2
窗口3正在卖:1
窗口2正在卖:1
窗口1正在卖:1
这类问题就称做线程安全问题,为了解决这个问题,能够采起一些线程同步的措施并发
当咱们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操做,就容易出现线程安全问题。ide
为了解决并发问题(线程同步问题),也就是多线程并发访问同一个资源,对这个资源进行写操做的问题,java中提供了线程同步(synchronized)来解决这个问题。atom
解决线程同步的方法:spa
方法1:同步代码块线程
同步代码块:synchronized加在代码块上,格式以下code
synchronized (lock){
//须要同步的代码块
....
}
方法2:同步锁
对象的同步锁只是一个概念,能够想象为在对象上标记了一个锁.
锁对象 能够是任意类型。
多个线程对象 要使用同一把锁。
方法3:同步方法
在方法进行同步,格式以下:
public synchronized void method(){
//须要同步的代码块
......
}
java.util.concurrent.locks.Lock
机制提供了比synchronized代码块和synchronized方法更普遍的锁定操做,同步代码块/同步方法具备的功能Lock都有,除此以外更强大,更体现面向对象。Lock锁也称同步锁,加锁与释放锁方法化了,以下:public void lock() :加同步锁。public void unlock() :释放同步锁。使用以下:
public class Tickets implements Runnable{
//初始化票数
private int ticket=100;
Lock lock = new ReentrantLock();
public void run() {
//卖票
while (true){
lock.lock();
if(ticket>0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
}
lock.unlock();
}
}
}
在java程序中,若是有多个线程同时运行,而且同时执行同一段代码,若是程序每次运行的结果和单线程运行的结果是同样的,并且其余变量的值也和预期是同样的,那么这段代码就是线程安全的。
可是在多线程操做中也可能会有一些线程安全的问题发生。
以卖票事例做为说明,有100张票往外售卖,售完结束。
public class Tickets implements Runnable{
//初始化票数
private int ticket=100;
public void run() {
//卖票
while (true){
if(ticket>0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
}
}
}
}
public class TicketsTest {
public static void main(String[] args) {
//声明变量
Tickets tickets = new Tickets();
//建立三个线程(窗口)
Thread t1 = new Thread(tickets,"窗口1");
Thread t2 = new Thread(tickets,"窗口2");
Thread t3 = new Thread(tickets,"窗口3");
//三个窗口同时买票
t1.start();
t2.start();
t3.start();
}
}
可是在运行结果中会发生如下这种状况:票已经卖出,可是总数没有减小;或者票已经售空,仍然在减票的状况
窗口3正在卖:100
窗口1正在卖:99
窗口2正在卖:100
窗口1正在卖:98
.......
窗口2正在卖:4
窗口1正在卖:2
窗口3正在卖:1
窗口2正在卖:1
窗口1正在卖:1
这类问题就称做线程安全问题,为了解决这个问题,能够采起一些线程同步的措施
当咱们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操做,就容易出现线程安全问题。
为了解决并发问题(线程同步问题),也就是多线程并发访问同一个资源,对这个资源进行写操做的问题,java中提供了线程同步(synchronized)来解决这个问题。
解决线程同步的方法:
方法1:同步代码块
同步代码块:synchronized加在代码块上,格式以下
synchronized (lock){
//须要同步的代码块
....
}
方法2:同步锁
对象的同步锁只是一个概念,能够想象为在对象上标记了一个锁.
锁对象 能够是任意类型。
多个线程对象 要使用同一把锁。
方法3:同步方法
在方法进行同步,格式以下:
public synchronized void method(){
//须要同步的代码块
......
}
java.util.concurrent.locks.Lock
机制提供了比synchronized代码块和synchronized方法更普遍的锁定操做,同步代码块/同步方法具备的功能Lock都有,除此以外更强大,更体现面向对象。Lock锁也称同步锁,加锁与释放锁方法化了,以下:public void lock() :加同步锁。public void unlock() :释放同步锁。使用以下:
public class Tickets implements Runnable{
//初始化票数
private int ticket=100;
Lock lock = new ReentrantLock();
public void run() {
//卖票
while (true){
lock.lock();
if(ticket>0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
}
lock.unlock();
}
}
}