diff --git a/django/conf/urls/defaults.py b/django/conf/urls/defaults.py
index 3ab8bab..1f6c71f 100644
--- a/django/conf/urls/defaults.py
+++ b/django/conf/urls/defaults.py
@@ -28,7 +28,7 @@ def patterns(prefix, *args):
     return pattern_list
 
 def url(regex, view, kwargs=None, name=None, prefix=''):
-    if isinstance(view, (list,tuple)):
+    if isinstance(view, (list, tuple)):
         # For include(...) processing.
         urlconf_module, app_name, namespace = view
         return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index cad57a5..06e61ba 100644
--- a/django/core/urlresolvers.py
+++ b/django/core/urlresolvers.py
@@ -81,6 +81,9 @@ def get_mod_func(callback):
     return callback[:dot], callback[dot+1:]
 
 class RegexURLPattern(object):
+    """
+    Represents a single pattern in a URLconf.
+    """
     def __init__(self, regex, callback, default_args=None, name=None):
         # regex is a string representing a regular expression.
         # callback is either a string like 'foo.views.news.stories.story_detail'
@@ -119,8 +122,12 @@ class RegexURLPattern(object):
                 args = match.groups()
             # In both cases, pass any extra_kwargs as **kwargs.
             kwargs.update(self.default_args)
-
-            return self.callback, args, kwargs
+            
+            # Instantiate classes each time the pattern is resolved
+            callback = self.callback
+            if isinstance(callback, type):
+                callback = callback()
+            return callback, args, kwargs
 
     def _get_callback(self):
         if self._callback is not None:
@@ -137,6 +144,9 @@ class RegexURLPattern(object):
     callback = property(_get_callback)
 
 class RegexURLResolver(object):
+    """
+    Resolves and reverses URLs in a URLconf.
+    """
     def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
         # regex is a string representing a regular expression.
         # urlconf_name is a string representing the module containing URLconfs.
diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt
index 5a2980f..68c260d 100644
--- a/docs/topics/http/urls.txt
+++ b/docs/topics/http/urls.txt
@@ -631,6 +631,26 @@ The style you use is up to you.
 Note that if you use this technique -- passing objects rather than strings --
 the view prefix (as explained in "The view prefix" above) will have no effect.
 
+Passing classes as views
+========================
+
+If you write your views as classes with a ``__call__()`` method, they may not be 
+thread safe if you pass them as instances to your URLconf. To ensure your 
+class-based views work correctly, you may pass a class which will be 
+instantiated on each request before being called::
+
+    urlpatterns = patterns('',
+        (r'^contact/$', 'mysite.views.ContactView'),
+    )
+
+You may also pass classes directly::
+
+    from mysite.views import ContactView
+    
+    urlpatterns = patterns('',
+        (r'^contact/$', ContactView),
+    )
+
 .. _naming-url-patterns:
 
 Naming URL patterns
diff --git a/tests/regressiontests/urlpatterns/__init__.py b/tests/regressiontests/urlpatterns/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/urlpatterns/models.py b/tests/regressiontests/urlpatterns/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/urlpatterns/tests.py b/tests/regressiontests/urlpatterns/tests.py
new file mode 100644
index 0000000..4be7708
--- /dev/null
+++ b/tests/regressiontests/urlpatterns/tests.py
@@ -0,0 +1,39 @@
+from django.test import TestCase
+
+class TestResolver(TestCase):
+    urls = 'regressiontests.urlpatterns.urls'
+    
+    def test_callable_view(self):
+        response = self.client.get('/callable-view/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.content, 'callable_view')
+    
+    def test_string_view(self):
+        response = self.client.get('/string-view/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.content, 'string_view')
+    
+    def test_new_instance_of_class_for_request(self):
+        """
+        When a class is passed as a view, ensure a new instance is created for
+        each request.
+        """
+        response = self.client.get('/class/new-instance/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.content, 'OneTimeView')
+        # This view will 404 if it is called a second time
+        self.assertEqual(
+            self.client.get('/class/new-instance/').status_code,
+            200
+        )
+    
+    def test_class_string_view(self):
+        """
+        Test class views can be passed as strings.
+        """
+        response = self.client.get('/class/string/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.content, 'StringView')
+        # Ensure new instances are creating for string views too
+        self.assertEqual(self.client.get('/class/string/').status_code, 200)
+
diff --git a/tests/regressiontests/urlpatterns/urls.py b/tests/regressiontests/urlpatterns/urls.py
new file mode 100644
index 0000000..7e6e0db
--- /dev/null
+++ b/tests/regressiontests/urlpatterns/urls.py
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import *
+from views import OneTimeView, callable_view
+
+urlpatterns = patterns('',
+    url(r'^callable-view/$', callable_view),
+    url(r'^string-view/$', 'regressiontests.urlpatterns.views.string_view'),
+    url(r'^class/new-instance/$', OneTimeView),
+    url(r'^class/string/$', 'regressiontests.urlpatterns.views.StringView'),
+)
diff --git a/tests/regressiontests/urlpatterns/views.py b/tests/regressiontests/urlpatterns/views.py
new file mode 100644
index 0000000..009824e
--- /dev/null
+++ b/tests/regressiontests/urlpatterns/views.py
@@ -0,0 +1,27 @@
+from django.http import HttpResponse, Http404
+
+def callable_view(request):
+    return HttpResponse('callable_view')
+
+def string_view(request):
+    return HttpResponse('string_view')
+
+class OneTimeView(object):
+    """
+    A view that will 404 the second time it is called.
+    """
+    
+    def __init__(self, *args, **kwargs):
+        super(OneTimeView, self).__init__(*args, **kwargs)
+        self.call_count = 0
+    
+    def __call__(self, request):
+        if self.call_count > 0:
+            raise Http404
+        self.call_count += 1
+        return HttpResponse(self.__class__.__name__)
+
+
+class StringView(OneTimeView):
+    pass
+
