a statically verifiable programming model for concurrent object-oriented programs
DESCRIPTION
A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs. Bart Jacobs 1 (≠ Prof. B. P. F. Jacobs, R.U.Nijmegen, The Netherlands) Joint work with Jan Smans 1 , Frank Piessens 1 , Wolfram Schulte 2 , Rustan Leino 2 1 K.U.Leuven, Belgium - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/1.jpg)
A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs
Bart Jacobs1 (≠ Prof. B. P. F. Jacobs, R.U.Nijmegen, The Netherlands)
Joint work with Jan Smans1, Frank Piessens1, Wolfram Schulte2 , Rustan Leino2
1 K.U.Leuven, Belgium
2 Microsoft Research, Redmond, WA, USA
![Page 2: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/2.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 3: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/3.jpg)
The Problem
Goal: Delivering correct concurrent Java programs
Problem: It’s hard to reason about such programs due to the non-local nature of data races, deadlocks, and object
aliasing
Proposed solution: A programming regime (or programming model)
that prevents data races and deadlocks, and enables local reasoning in the presence of object aliasing.
An annotation syntax and verification approach that enables modular static verification of compliance with the
programming model.
![Page 4: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/4.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 5: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/5.jpg)
Data Races
class Account { int balance; }
Account act = …;
int b0 = act.balance;
act.balance += 50;
int b1 = act.balance;
b1 == b0 + 50? Not necessarily!
![Page 6: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/6.jpg)
Data Races
class Account { int balance; }
Account act = …; int b0, b1;
synchronized (act) {
b0 = act.balance;
act.balance += 50;
b1 = act.balance;
}
b1 == b0 + 50? Not necessarily!
![Page 7: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/7.jpg)
Data Races
class Account { int balance; }
Account act = …; int b0, b1;
synchronized (act) {
b0 = act.balance;
act.balance += 50;
b1 = act.balance;
}
b1 == b0 + 50? Not necessarily!
In Java, it’s not sound to reason sequentially about sequential code
due to the possibility of data races.
![Page 8: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/8.jpg)
Preventing data races: Access sets Per-thread access set t.A
x = o.f; or o.f = x; requires o in t.A
Always: t1 != t2 ==> t1.A and t2.A disjoint
Object can move between access sets only via proper synchronization
![Page 9: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/9.jpg)
Preventing data races: Access sets x := new C; implies x in t.A’
entering synchronized (o) implies o in t.A’
exiting synchronized (o) implies o not in t.A’
![Page 10: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/10.jpg)
Preventing data races: Access sets x := new C; implies x in t.A’
entering synchronized (o) implies o in t.A’
exiting synchronized (o) implies o not in t.A’
But: races between creating thread and locking thread?
![Page 11: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/11.jpg)
Preventing data races:Shared and unshared objects x := new C; implies x is unshared’
attempting synchronized (o) requires x is shared
programmer indicates share o; requires o in t.A and o is unshared implies o is not in t.A’ and o is shared’
shared objects never become unshared again
Property: If a shared object o is not locked by any thread, then it is not in any thread’s access set.
![Page 12: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/12.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Ashared
![Page 13: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/13.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Asharedx
![Page 14: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/14.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Asharedx
![Page 15: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/15.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t1.Asharedx
![Page 16: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/16.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
![Page 17: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/17.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
![Page 18: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/18.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
![Page 19: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/19.jpg)
Preventing data races
// thread 1:
x := new C;
x.f := 5;
share x;
// start thread 2
// thread 2:
synchronized (x) {
int n := x.f;
}
t2.A
sharedx
t1.A
![Page 20: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/20.jpg)
Thread creation
new Thread(r).start() requires r in t.A implies r not in t.A’
in new thread: r in t.A
![Page 21: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/21.jpg)
Preventing Data Races: Lock Re-entry Causes difficulties for method effect framing
We disallow it
![Page 22: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/22.jpg)
Preventing data races:Modular Static Verification Annotations required:
Share commands Method contracts
requires/ensures o is in tid.A (tid = current thread) requires/ensures o is unshared/shared requires/ensures o is not in tid.lockset/tid.lockset is empty
Field modifier: shared
Verification approach: Verification condition generation On entry to synchronized block:
foreach (o.f where o not in t.A) { o.f := random; } Method effect framing: required access sets
![Page 23: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/23.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
![Page 24: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/24.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
main.Ashared
main
![Page 25: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/25.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
main
![Page 26: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/26.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
main
![Page 27: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/27.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
main
![Page 28: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/28.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
main
![Page 29: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/29.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
s1.A
main
s1
![Page 30: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/30.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
s2
s1.A
main
s1
![Page 31: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/31.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1
s2
s1.A
main
s1
![Page 32: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/32.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s1s2
![Page 33: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/33.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s1s2
![Page 34: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/34.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s1
s2
![Page 35: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/35.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s2
![Page 36: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/36.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s2
![Page 37: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/37.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
s2
![Page 38: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/38.jpg)
Preventing data races: Exampleclass Counter {
int count;
}
class Session implements Runnable {
shared Counter counter;
public void run()
requires this in tid.A;
requires tid.lockset is empty;
{
synchronized (counter) {
counter.count++;
}
}
}
Counter counter = new Counter();
share counter;
Session session1 = new Session();
session1.counter = counter;
new Thread(session1).start();
Session session2 = new Session();
session2.counter = counter;
new Thread(session2).start();
c
main.Ashared
s1 s2
s1.As2.A
![Page 39: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/39.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 40: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/40.jpg)
Preventing deadlocks
Deadlock = cycle of threads each waiting for the next to release a lock
Proposed solution: Programmer constructs partially ordered set of lock levels
using l := between({ll1,...,lln},{lu1,...,lum}); annotation Assigns a lock level to each shared object A thread may attempt to acquire an object’s lock only if the object
is below the objects whose lock it already holds
![Page 41: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/41.jpg)
Preventing deadlocks: exampleclass Fork {}
class Philosopher implements Runnable {
shared Fork fa, fb;
Philosopher(Fork fa, Fork fb) requires fa.locklevel < fb.locklevel;
{ this.fa = fa; this.fb = fb; }
public void run() requires this in tid.A and lockset is empty;
{ synchronized (fb) { synchronized (fa) { /* eat */ } } }
}
Fork f1 = new Fork(); locklevel l1 = between({},{}); share f1 at l1;
Fork f2 = new Fork(); locklevel l2 = between({l1},{}); share f2 at l2;
Fork f3 = new Fork(); locklevel l3 = between({l2},{}); share f3 at l3;
new Thread(new Philosopher(f1, f2)).start();
new Thread(new Philosopher(f2, f3)).start();
new Thread(new Philosopher(f1, f3)).start();
![Page 42: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/42.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 43: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/43.jpg)
Rep Objects Objects often use auxiliary objects to help represent their
state e.g. an ArrayList uses an array object
We wish to protect the array object against data races using the lock of the ArrayList object
Proposed solution: use Spec#’s ownership system Fields may be marked with rep modifier The objects pointed to by o’s rep fields are its rep objects An object may be packed or unpacked When an object is in the packed state, it owns its rep objects A thread can gain access to an owned object by locking the
owner and then unpacking the owner
![Page 44: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/44.jpg)
Ownership system
When packing an object o, using a pack o; annotation, o’s rep objects are removed from tid.A
When unpacking o, using an unpack o; annotation, o’s rep objects are added to tid.A
![Page 45: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/45.jpg)
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
![Page 46: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/46.jpg)
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
t.Ashared
![Page 47: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/47.jpg)
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
bl
t.Ashared
![Page 48: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/48.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 49: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/49.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 50: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/50.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 51: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/51.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 52: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/52.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 53: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/53.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 54: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/54.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 55: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/55.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 56: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/56.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 57: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/57.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 58: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/58.jpg)
bl
Ownership system: Exampleclass BoundedList {
rep Object[] elements;
int count;
BoundedList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
}
BoundedList bl = new BoundedList();
share bl;
synchronized (bl) {
bl.add(null);
}
es
t.Ashared
![Page 59: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/59.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 60: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/60.jpg)
Object invariantsclass Account { int balance;
Account() ensures this in tid.A; {
} void deposit(int amount) requires this in tid.A && 0 <= amount; ensures this in tid.A; {
balance += amount;
}}
Account a = new Account();share a;…synchronized (a) { assert 0 <= a.balance; // does not verify}
![Page 61: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/61.jpg)
Object invariantsclass Account { int balance; invariant 0 <= balance; Account() ensures this in tid.A && this is packed; { pack this; } void deposit(int amount) requires this in tid.A && this is packed && 0 <= amount; ensures this in tid.A && this is packed; { unpack this; balance += amount; pack this; }}
Account a = new Account();share a;…synchronized (a) { assert 0 <= a.balance; // verifies!}
![Page 62: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/62.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 63: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/63.jpg)
Immutable objectsclass BoundedList {
rep Object[] elements;
int count;
ArrayList(int capacity)
ensures this is in tid.A and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
Object get(int index)
requires this is in tid.A and this is packed;
ensures this is in tid.A and this is packed;
{
unpack this; Object v = elements[index]; pack this;
return v;
}
}
class RsaServer implements Runnable {
shared BoundedList primes;
RsaServer(BoundedList primes)
requires primes is shared;
ensures this is in tid.A and this is packed;
{ this.primes = primes; pack this; }
public void run()
requires lockset is empty;
requires this is in tid.A and this is packed;
{
synchronized (primes) {
/* perform RSA operations */
… int p = primes[…]; …
}
}
}
BoundedList primes = new BoundedList();
fillWithPrimes(primes);
share primes;
new Thread(new RsaServer(primes)).start();
new Thread(new RsaServer(primes)).start();
![Page 64: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/64.jpg)
Immutable objectsclass BoundedList {
rep Object[] elements;
int count;
ArrayList(int capacity)
ensures this is in tid.W and this is packed;
{
elements = new Object[capacity];
pack this;
}
void add(Object value)
requires this is in tid.W and this is packed;
ensures this is in tid.W and this is packed;
{
unpack this;
elements[count++] = value;
pack this;
}
Object get(int index)
requires this is in tid.R and this is packed;
{
read (this) { return elements[index]; }
}
}
class RsaServer implements Runnable {
shared_immutable BoundedList primes;
RsaServer(BoundedList primes)
requires primes is shared_immutable;
ensures this is in tid.W and this is packed;
{ this.primes = primes; pack this; }
public void run()
requires lockset is empty;
requires this is in tid.W and this is packed;
{
/* perform RSA operations */
… int p = primes[…]; …
}
}
BoundedList primes = new BoundedList();
fillWithPrimes(primes);
share_immutable primes;
new Thread(new RsaServer(primes)).start();
new Thread(new RsaServer(primes)).start();
![Page 65: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/65.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 66: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/66.jpg)
Related Work
ESC/Modula3, ESC/Java, RCC/Java Calvin/R Safe Concurrent Java Atomicity JML Separation logic Monitor invariants Assertional proof system for monitors Dynamic tools: Eraser, RaceTrack Software Transactional Memory
![Page 67: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/67.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 68: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/68.jpg)
Future work
Integrating support for module invariants and rely-guarantee conditions
Verification of non-blocking algorithms (volatile, CAS)
Verification of additional liveness properties
![Page 69: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/69.jpg)
Outline of the Talk
Progressive refinement of the approach: Absence of data races Absence of deadlocks Ownership Object invariants Immutable objects
Related work, future work, conclusion
![Page 70: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/70.jpg)
Conclusion
Programming model and static verification approach
that prevents data races and deadlocks
and supports local reasoning in the presence of object aliasing, using an ownership system.
Has support for object invariants immutable objects
![Page 71: A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs](https://reader035.vdocuments.us/reader035/viewer/2022081603/56813561550346895d9cc6bb/html5/thumbnails/71.jpg)
A Statically Verifiable Programming Model for Concurrent Object-Oriented Programs
Bart Jacobs1
Joint work with Jan Smans1, Frank Piessens1, Wolfram Schulte2 , Rustan Leino2
1 K.U.Leuven, Belgium
2 Microsoft Research, Redmond, WA, USA